From 06a102072470b9cfd56c7ca4700c4316370ae9ac Mon Sep 17 00:00:00 2001 From: Gio Date: Thu, 22 Dec 2016 00:33:34 +0100 Subject: [PATCH] Add workaround to see debug messages from native code in android service --- libretroshare/src/libretroshare.pro | 2 + libretroshare/src/util/androiddebug.h | 117 +++++++++++++++++++++ retroshare-android-service/src/service.cpp | 6 ++ 3 files changed, 125 insertions(+) create mode 100644 libretroshare/src/util/androiddebug.h diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 16b5a84c5..35b34481c 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -910,4 +910,6 @@ android-g++ { INCLUDEPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include DEPENDPATH += $$NDK_TOOLCHAIN_PATH/sysroot/usr/include PRE_TARGETDEPS += $$NDK_TOOLCHAIN_PATH/sysroot/usr/lib/libcrypto.a + + HEADERS += util/androiddebug.h } diff --git a/libretroshare/src/util/androiddebug.h b/libretroshare/src/util/androiddebug.h new file mode 100644 index 000000000..2e429b99f --- /dev/null +++ b/libretroshare/src/util/androiddebug.h @@ -0,0 +1,117 @@ +#pragma once +/* + * Redirect plain stdout and stderr to Android debug + * Copyright (C) 2016 Gioacchino Mazzurco + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +// Inspired by: https://codelab.wordpress.com/2014/11/03/how-to-use-standard-output-streams-for-logging-in-android-apps/ + +#include +#include +#include +#include // for O_NONBLOCK +#include +#include +#include + +/** + * On Android stdout and stderr of native code is discarded, instancing this + * class at the beginning of the main of your program to get them (stdout and + * stderr) on logcat output. + */ +class AndroidStdIOCatcher +{ +public: + AndroidStdIOCatcher(const std::string& dTag = "RetroShare", + android_LogPriority stdout_pri = ANDROID_LOG_INFO, + android_LogPriority stderr_pri = ANDROID_LOG_ERROR) : + tag(dTag), cout_pri(stdout_pri), cerr_pri(stderr_pri), should_stop(false) + { + // make stdout line-buffered + //setvbuf(stdout, 0, _IOLBF, 0); + + // make stdout and stderr unbuffered + setvbuf(stdout, 0, _IONBF, 0); + setvbuf(stderr, 0, _IONBF, 0); + + // create the pipes and redirect stdout and stderr + pipe2(pout_fd, O_NONBLOCK); + dup2(pout_fd[1], STDOUT_FILENO); + + pipe2(perr_fd, O_NONBLOCK); + dup2(perr_fd[1], STDERR_FILENO); + + // spawn the logging thread + pthread_create(&thr, 0, thread_func, this); + pthread_detach(thr); + } + + ~AndroidStdIOCatcher() + { + should_stop = true; + pthread_join(thr, NULL); + } + +private: + const std::string tag; + const android_LogPriority cout_pri; + const android_LogPriority cerr_pri; + + int pout_fd[2]; + int perr_fd[2]; + pthread_t thr; + std::atomic should_stop; + + static void *thread_func(void* instance) + { + __android_log_write(ANDROID_LOG_INFO, "RetroShare", "Android debugging start"); + + AndroidStdIOCatcher &i = *static_cast(instance); + + std::string out_buf; + std::string err_buf; + + while (!i.should_stop) + { + for(char c; read(i.pout_fd[0], &c, 1) == 1;) + { + out_buf += c; + if(c == '\n') + { + __android_log_write(i.cout_pri, i.tag.c_str(), out_buf.c_str()); + out_buf.clear(); + } + } + + for(char c; read(i.perr_fd[0], &c, 1) == 1;) + { + err_buf += c; + if(c == '\n') + { + __android_log_write(i.cerr_pri, i.tag.c_str(), err_buf.c_str()); + err_buf.clear(); + } + } + + usleep(10000); + } + + __android_log_write(ANDROID_LOG_INFO, "RetroShare", "Android debugging stop"); + + return NULL; + } +}; + diff --git a/retroshare-android-service/src/service.cpp b/retroshare-android-service/src/service.cpp index 9359af904..d3759dc61 100644 --- a/retroshare-android-service/src/service.cpp +++ b/retroshare-android-service/src/service.cpp @@ -21,6 +21,7 @@ #ifdef __ANDROID__ # include +# include "util/androiddebug.h" #endif #include "retroshare/rsinit.h" @@ -28,10 +29,15 @@ #include "api/ApiServerLocal.h" #include "api/RsControlModule.h" + using namespace resource_api; int main(int argc, char *argv[]) { +#ifdef __ANDROID__ + AndroidStdIOCatcher dbg; (void) dbg; +#endif + QCoreApplication a(argc, argv); ApiServer api; RsControlModule ctrl_mod(argc, argv, api.getStateTokenServer(), &api, true);