--- a/src/demo/input.c +++ b/src/demo/input.c @@ -4,6 +4,15 @@ #include #include "demo.h" +#ifdef __ANDROID__ +#define PTHREAD_CANCELED ((void *)-1) +static void +thread_signal_handler(int signum) +{ + pthread_exit(PTHREAD_CANCELED); +} +#endif + typedef struct nciqueue { ncinput ni; struct nciqueue *next; @@ -118,6 +127,15 @@ static void * ultramegaok_demo(void* vnc){ +#ifdef __ANDROID__ + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_signal_handler; + sigaction(SIGUSR2, &actions, NULL); +#endif + ncinput ni; struct notcurses* nc = vnc; uint32_t id; @@ -176,7 +194,11 @@ int stop_input(void){ int ret = 0; if(input_pipefds[0] >= 0){ +#ifndef __ANDROID__ ret |= pthread_cancel(tid); +#else + ret |= pthread_kill(tid, SIGUSR2); +#endif ret |= pthread_join(tid, NULL); ret |= close(input_pipefds[0]); ret |= close(input_pipefds[1]); --- a/src/demo/reel.c +++ b/src/demo/reel.c @@ -7,6 +7,15 @@ #include #include "demo.h" +#ifdef __ANDROID__ +#define PTHREAD_CANCELED ((void *)-1) +static void +thread_signal_handler(int signum) +{ + pthread_exit(PTHREAD_CANCELED); +} +#endif + #define INITIAL_TABLET_COUNT 4 static pthread_mutex_t renderlock = PTHREAD_MUTEX_INITIALIZER; @@ -27,9 +36,13 @@ kill_tablet(tabletctx** tctx){ tabletctx* t = *tctx; if(t){ +#ifndef __ANDROID__ if(pthread_cancel(t->tid)){ fprintf(stderr, "Warning: error sending pthread_cancel (%s)\n", strerror(errno)); } +#else + pthread_kill(t->tid, SIGUSR2); +#endif if(pthread_join(t->tid, NULL)){ fprintf(stderr, "Warning: error joining pthread (%s)\n", strerror(errno)); } @@ -117,6 +130,15 @@ // events for its tablet. static void* tablet_thread(void* vtabletctx){ +#ifdef __ANDROID__ + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_signal_handler; + sigaction(SIGUSR2, &actions, NULL); +#endif + static int MINSECONDS = 0; tabletctx* tctx = vtabletctx; while(true){ --- a/src/demo/outro.c +++ b/src/demo/outro.c @@ -1,6 +1,10 @@ #include #include "demo.h" +#ifdef __ANDROID__ +#define PTHREAD_CANCELED ((void *)-1) +#endif + static int y; static int targy; static unsigned xstart; --- a/src/lib/fd.c +++ b/src/lib/fd.c @@ -23,6 +23,15 @@ #define NCPOLLEVENTS (POLLIN) #endif +#ifdef __ANDROID__ +#define PTHREAD_CANCELED ((void *)-1) +static void +thread_signal_handler(int signum) +{ + pthread_exit(PTHREAD_CANCELED); +} +#endif + // release the memory and fd, but don't join the thread (since we might be // getting called within the thread's context, on a callback). static int @@ -85,6 +94,15 @@ static void * ncfdplane_thread(void* vncfp){ +#ifdef __ANDROID__ + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_signal_handler; + sigaction(SIGUSR2, &actions, NULL); +#endif + fdthread(vncfp, -1); return NULL; } @@ -266,6 +284,15 @@ // need a poll on both main fd and pidfd static void * ncsubproc_thread(void* vncsp){ +#ifdef __ANDROID__ + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_signal_handler; + sigaction(SIGUSR2, &actions, NULL); +#endif + int* status = malloc(sizeof(*status)); if(status){ ncsubproc* ncsp = vncsp; @@ -287,6 +314,15 @@ // wake up our poll()ing thread). static void * ncsubproc_waiter(void* vncsp){ +#ifdef __ANDROID__ + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = thread_signal_handler; + sigaction(SIGUSR2, &actions, NULL); +#endif + ncsubproc* ncsp = vncsp; int* status = malloc(sizeof(*status)); pid_t pid; @@ -425,7 +461,11 @@ // then exits. don't try to cancel the thread in that case; rely instead on // killing the subprocess. if(n->pidfd < 0){ +#ifndef __ANDROID__ pthread_cancel(n->nfp->tid); +#else + pthread_kill(n->nfp->tid, SIGUSR2); +#endif // shouldn't need a cancellation of waittid thanks to SIGKILL pthread_join(n->waittid, &vret); } --- a/src/lib/in.c +++ b/src/lib/in.c @@ -7,6 +7,15 @@ #include "render.h" #include "in.h" +#ifdef __ANDROID__ +#define PTHREAD_CANCELED ((void *)-1) +static void +thread_signal_handler(int signum) +{ + pthread_exit(PTHREAD_CANCELED); +} +#endif + // Notcurses takes over stdin, and if it is not connected to a terminal, also // tries to make a connection to the controlling terminal. If such a connection // is made, it will read from that source (in addition to stdin). We dump one or @@ -2498,6 +2507,14 @@ static void* input_thread(void* vmarshall){ setup_alt_sig_stack(); +#ifdef __ANDROID__ + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = SA_ONSTACK; + actions.sa_handler = thread_signal_handler; + sigaction(SIGUSR2, &actions, NULL); +#endif inputctx* ictx = vmarshall; if(prep_all_keys(ictx) || build_cflow_automaton(ictx)){ ictx->failed = true; --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -1832,9 +1832,13 @@ // have already exited), and then join it (an error here is propagated). static inline int cancel_and_join(const char* name, pthread_t tid, void** res){ +#ifndef __ANDROID__ if(pthread_cancel(tid)){ logerror("couldn't cancel %s thread", name); // tid might have died } +#else + pthread_kill(tid, SIGUSR2); +#endif if(pthread_join(tid, res)){ logerror("error joining %s thread", name); return -1;