OSDN Git Service

Avoid crash when M structure free just before thread exit.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 22 Jan 2011 02:59:24 +0000 (02:59 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 22 Jan 2011 02:59:24 +0000 (02:59 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@169121 138bc75d-0d04-0410-961f-82ee72b054a4

libgo/runtime/go-go.c
libgo/runtime/thread.c

index 3146268..8c2de28 100644 (file)
@@ -94,6 +94,13 @@ remove_current_thread (void)
 
   runtime_MCache_ReleaseAll (mcache);
 
+  /* As soon as we release this look, a GC could run.  Since this
+     thread is no longer on the list, the GC will not find our M
+     structure, so it could get freed at any time.  That means that
+     any code from here to thread exit must not assume that the m is
+     valid.  */
+  m = NULL;
+
   i = pthread_mutex_unlock (&__go_thread_ids_lock);
   __go_assert (i == 0);
 
index 99a0d68..c4e7f6c 100644 (file)
@@ -38,9 +38,11 @@ runtime_lock_full(Lock *l)
 void
 runtime_lock(Lock *l)
 {
-       if(m->locks < 0)
-               runtime_throw("lock count");
-       m->locks++;
+       if(m != nil) {
+               if(m->locks < 0)
+                       runtime_throw("lock count");
+               m->locks++;
+       }
 
        if(runtime_xadd(&l->key, 1) > 1)        // someone else has it; wait
                runtime_lock_full(l);
@@ -58,9 +60,11 @@ runtime_unlock_full(Lock *l)
 void
 runtime_unlock(Lock *l)
 {
-       m->locks--;
-       if(m->locks < 0)
-               runtime_throw("lock count");
+       if(m != nil) {
+               m->locks--;
+               if(m->locks < 0)
+                       runtime_throw("lock count");
+       }
 
        if(runtime_xadd(&l->key, -1) > 0)       // someone else is waiting
                runtime_unlock_full(l);