Native traditional signal to interrupt thread

This commit is contained in:
M66B 2016-01-13 12:15:46 +01:00
parent 36ce001643
commit 5086ff800e
2 changed files with 54 additions and 26 deletions

View File

@ -665,6 +665,8 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
PendingIntent pi = PendingIntent.getActivity(this, 0, configure, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pi = PendingIntent.getActivity(this, 0, configure, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setConfigureIntent(pi); builder.setConfigureIntent(pi);
builder.setBlocking(true);
// Start VPN service // Start VPN service
try { try {
return builder.establish(); return builder.establish();

View File

@ -78,7 +78,6 @@ char *hex(const u_int8_t *, const u_int16_t);
static JavaVM *jvm; static JavaVM *jvm;
int running = 0; int running = 0;
int stopped = 1;
pthread_t thread_id; pthread_t thread_id;
struct connection *connection = NULL; struct connection *connection = NULL;
@ -92,25 +91,29 @@ Java_eu_faircode_netguard_SinkholeService_jni_1start(JNIEnv *env, jobject instan
if (rs != JNI_OK) if (rs != JNI_OK)
__android_log_print(ANDROID_LOG_ERROR, TAG, "GetJavaVM failed"); __android_log_print(ANDROID_LOG_ERROR, TAG, "GetJavaVM failed");
running = 1;
struct arguments *args = malloc(sizeof(struct arguments)); struct arguments *args = malloc(sizeof(struct arguments));
args->instance = (*env)->NewGlobalRef(env, instance); args->instance = (*env)->NewGlobalRef(env, instance);
args->tun = tun; args->tun = tun;
if (pthread_create(&thread_id, NULL, handle_events, args) != 0) { if (pthread_create(&thread_id, NULL, handle_events, args) != 0)
running = 0;
__android_log_print(ANDROID_LOG_ERROR, TAG, "pthread_create error %d: %s", __android_log_print(ANDROID_LOG_ERROR, TAG, "pthread_create error %d: %s",
errno, strerror(errno)); errno, strerror(errno));
} else
running = 1;
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_eu_faircode_netguard_SinkholeService_jni_1stop(JNIEnv *env, jobject instance, jint tun) { Java_eu_faircode_netguard_SinkholeService_jni_1stop(JNIEnv *env, jobject instance, jint tun) {
running = 0; __android_log_print(ANDROID_LOG_DEBUG, TAG, "Stop");
while (!stopped) { if (running) {
// TODO interrupt thread int err = pthread_kill(thread_id, SIGUSR1);
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopping"); if (err != 0)
nsleep(1000 * 1000L * 1000L); __android_log_print(ANDROID_LOG_WARN, TAG, "pthread_kill error %d", err);
} pthread_join(thread_id, NULL);
if (err != 0)
__android_log_print(ANDROID_LOG_WARN, TAG, "pthread_join error %d", err);
running = 0;
} else
__android_log_print(ANDROID_LOG_WARN, TAG, "Notrunning");
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopped"); __android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopped");
} }
@ -124,6 +127,10 @@ Java_eu_faircode_netguard_SinkholeService_jni_1reload(JNIEnv *env, jobject insta
// Private functions // Private functions
void sig_handler(int sig, siginfo_t *info, void *context) {
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Signal %d", sig);
}
void *handle_events(void *a) { void *handle_events(void *a) {
struct arguments *args = (struct arguments *) a; struct arguments *args = (struct arguments *) a;
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Start events tun=%d", args->tun); __android_log_print(ANDROID_LOG_DEBUG, TAG, "Start events tun=%d", args->tun);
@ -137,11 +144,25 @@ void *handle_events(void *a) {
fd_set rfds; fd_set rfds;
fd_set wfds; fd_set wfds;
fd_set efds; fd_set efds;
struct timeval tv; struct timespec ts;
char dest[20]; char dest[20];
sigset_t blockset;
sigset_t emptyset;
struct sigaction sa;
stopped = 0; // Block SIGUSR1
while (running) { sigemptyset(&blockset);
sigaddset(&blockset, SIGUSR1);
sigprocmask(SIG_BLOCK, &blockset, NULL);
/// Handle SIGUSR1
sa.sa_sigaction = sig_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGUSR1, &sa, NULL);
// Loop
while (1) {
time_t now = time(NULL); time_t now = time(NULL);
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Select"); __android_log_print(ANDROID_LOG_DEBUG, TAG, "Select");
@ -213,14 +234,20 @@ void *handle_events(void *a) {
cur = cur->next; cur = cur->next;
} }
tv.tv_sec = 10; ts.tv_sec = 10;
tv.tv_usec = 0; ts.tv_nsec = 0;
int ready = select(max + 1, &rfds, &wfds, &efds, &tv); sigemptyset(&emptyset);
int ready = pselect(max + 1, &rfds, &wfds, &efds, &ts, &emptyset);
if (ready < 0) { if (ready < 0) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "select error %d: %s", if (errno == EINTR) {
errno, strerror(errno)); __android_log_print(ANDROID_LOG_INFO, TAG, "pselect interrupted");
nsleep(1000 * 1000L * 1000L); break;
continue; } else {
__android_log_print(ANDROID_LOG_ERROR, TAG, "select error %d: %s",
errno, strerror(errno));
nsleep(1000 * 1000L * 1000L);
continue;
}
} }
if (ready == 0) if (ready == 0)
@ -229,7 +256,6 @@ void *handle_events(void *a) {
// Check tun // Check tun
if (FD_ISSET(args->tun, &efds)) { if (FD_ISSET(args->tun, &efds)) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "tun exception"); __android_log_print(ANDROID_LOG_ERROR, TAG, "tun exception");
running = 0;
break; break;
} }
@ -239,13 +265,14 @@ void *handle_events(void *a) {
if (length < 0) { if (length < 0) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "tun read error %d: %s", __android_log_print(ANDROID_LOG_ERROR, TAG, "tun read error %d: %s",
errno, strerror(errno)); errno, strerror(errno));
running = 0;
break; break;
} }
if (length > 0) if (length > 0)
decode(env, args->instance, buffer, length); decode(env, args->instance, buffer, length);
else else {
__android_log_print(ANDROID_LOG_DEBUG, TAG, "tun empty read"); __android_log_print(ANDROID_LOG_ERROR, TAG, "tun empty read");
break;
}
} }
// Check sockets // Check sockets
@ -324,7 +351,6 @@ void *handle_events(void *a) {
__android_log_print(ANDROID_LOG_ERROR, TAG, "DetachCurrentThread failed"); __android_log_print(ANDROID_LOG_ERROR, TAG, "DetachCurrentThread failed");
free(args); free(args);
stopped = 1;
__android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopped events tun=%d", args->tun); __android_log_print(ANDROID_LOG_DEBUG, TAG, "Stopped events tun=%d", args->tun);
} }