aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-01-22 02:59:24 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-01-22 02:59:24 +0000
commit47ba04ab544664fefe22f0e49e2307647bc33af5 (patch)
tree58887361507ba23f1681fa01255148350d978908 /libgo
parent039868965d6679379f1b87b7336986605229430b (diff)
downloadgcc-47ba04ab544664fefe22f0e49e2307647bc33af5.zip
gcc-47ba04ab544664fefe22f0e49e2307647bc33af5.tar.gz
gcc-47ba04ab544664fefe22f0e49e2307647bc33af5.tar.bz2
Avoid crash when M structure free just before thread exit.
From-SVN: r169121
Diffstat (limited to 'libgo')
-rw-r--r--libgo/runtime/go-go.c7
-rw-r--r--libgo/runtime/thread.c16
2 files changed, 17 insertions, 6 deletions
diff --git a/libgo/runtime/go-go.c b/libgo/runtime/go-go.c
index 3146268..8c2de28 100644
--- a/libgo/runtime/go-go.c
+++ b/libgo/runtime/go-go.c
@@ -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);
diff --git a/libgo/runtime/thread.c b/libgo/runtime/thread.c
index 99a0d68..c4e7f6c 100644
--- a/libgo/runtime/thread.c
+++ b/libgo/runtime/thread.c
@@ -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);