[android] pthread_kill cannot be used safely on android
authorGeoff Norton <grompf@sublimeintervention.com>
Thu, 14 Oct 2010 16:53:01 +0000 (12:53 -0400)
committerGeoff Norton <grompf@sublimeintervention.com>
Thu, 14 Oct 2010 17:02:11 +0000 (13:02 -0400)
Android's fork() function does not properly update the
pthread_internal_t->threadid variable to point to the tid of the
fork()'d thread, and instead still points to the pid of zygote.
As a result we need to track the android tid's manually since
gettid() is sane, and use an alternate to pthread_kill on android
Additionally, disable sgen support on android until the same
work has been done there

r: kumpera, vargaz

libgc/pthread_stop_world.c
mono/metadata/object-internals.h
mono/metadata/sgen-gc.c
mono/metadata/threads.c
mono/mini/debugger-agent.c

index 603aff7866221122aaff8bfd42b84f986f0c714a..5a1b9f37172db62df18dabaa9468a422e07c2058 100644 (file)
@@ -315,6 +315,7 @@ pthread_t GC_stopping_thread;
 int GC_stopping_pid;
 
 #ifdef PLATFORM_ANDROID
+static
 int android_thread_kill(pid_t tid, int sig)
 {
     int  ret;
index 7f1755e9baba73b5e3c737f40a4f582ca5284b7d..ce580faf6c3360be9d7f2cb6c866c601ac05f3a3 100644 (file)
@@ -401,11 +401,11 @@ struct _MonoInternalThread {
        MonoThread *root_domain_thread;
        gpointer interrupt_on_stop;
        gsize    flags;
+       gpointer android_tid;
        /* 
         * These fields are used to avoid having to increment corlib versions
         * when a new field is added to the unmanaged MonoThread structure.
         */
-       gpointer unused4;
        gpointer unused5;
        gpointer unused6;
 };
@@ -646,6 +646,9 @@ mono_type_initialization_init (void) MONO_INTERNAL;
 void
 mono_type_initialization_cleanup (void) MONO_INTERNAL;
 
+int
+mono_thread_kill           (MonoInternalThread *thread, int signal) MONO_INTERNAL;
+
 guint32
 mono_thread_get_tls_key    (void) MONO_INTERNAL;
 
index a36d35f35b3fe8c99a799f0c358df5f4e76f49e8..9384e7e0698565cb960677824867dfcdd40d9074 100644 (file)
@@ -6471,6 +6471,10 @@ mono_gc_base_init (void)
        char *major_collector_opt = NULL;
        struct sigaction sinfo;
 
+#ifdef PLATFORM_ANDROID
+       g_assert_not_reached ();
+#endif
+
        /* the gc_initialized guard seems to imply this method is
           idempotent, but LOCK_INIT(gc_mutex) might not be.  It's
           defined in sgen-gc.h as nothing, so there's no danger at
index e9c4b79210609295deda5f5963c473d32f9cbc50..3f934655c831f402f0ca35a1087866645016b5e3 100644 (file)
 
 #include <mono/metadata/gc-internal.h>
 
+#ifdef PLATFORM_ANDROID
+#include <errno.h>
+
+extern int tkill (pid_t tid, int signal);
+#endif
+
 /*#define THREAD_DEBUG(a) do { a; } while (0)*/
 #define THREAD_DEBUG(a)
 /*#define THREAD_WAIT_DEBUG(a) do { a; } while (0)*/
@@ -1014,6 +1020,9 @@ mono_thread_attach (MonoDomain *domain)
 
        thread->handle=thread_handle;
        thread->tid=tid;
+#ifdef PLATFORM_ANDROID
+       thread->android_tid = (gpointer) gettid ();
+#endif
        thread->apartment_state=ThreadApartmentState_Unknown;
        small_id_alloc (thread);
        thread->stack_ptr = &tid;
@@ -2300,11 +2309,7 @@ static void signal_thread_state_change (MonoInternalThread *thread)
        QueueUserAPC ((PAPCFUNC)interruption_request_apc, thread->handle, NULL);
 #else
        /* fixme: store the state somewhere */
-#ifdef PTHREAD_POINTER_ID
-       pthread_kill ((gpointer)(gsize)(thread->tid), mono_thread_get_abort_signal ());
-#else
-       pthread_kill (thread->tid, mono_thread_get_abort_signal ());
-#endif
+       mono_thread_kill (thread, mono_thread_get_abort_signal ());
 
        /* 
         * This will cause waits to be broken.
@@ -4334,3 +4339,30 @@ mono_runtime_has_tls_get (void)
 {
        return has_tls_get;
 }
+
+int
+mono_thread_kill (MonoInternalThread *thread, int signal)
+{
+#ifdef PTHREAD_POINTER_ID
+       return pthread_kill ((gpointer)(gsize)(thread->tid), mono_thread_get_abort_signal ());
+#else
+#  ifdef PLATFORM_ANDROID
+       if (thread->android_tid != 0) {
+               int  ret;
+               int  old_errno = errno;
+
+               ret = tkill ((pid_t) thread->android_tid, signal);
+               if (ret < 0) {
+                       ret = errno;
+                       errno = old_errno;
+               }
+
+               return ret;
+       }
+       else
+               return pthread_kill (thread->tid, mono_thread_get_abort_signal ());
+#  else
+       return pthread_kill (thread->tid, mono_thread_get_abort_signal ());
+#  endif
+#endif
+}
index e205ede5c8f1f64f423e1b88ec7e284f4d92459b..548a4ddd208380e2960627620ad74278d23afe1c 100644 (file)
@@ -2041,7 +2041,7 @@ notify_thread (gpointer key, gpointer value, gpointer user_data)
 #ifdef HOST_WIN32
        QueueUserAPC (notify_thread_apc, thread->handle, NULL);
 #else
-       pthread_kill ((pthread_t) tid, mono_thread_get_abort_signal ());
+       mono_thread_kill (thread, mono_thread_get_abort_signal ());
 #endif
 }