call C library free directly instead of System::free where possible

There was a subtle race condition in the VM shutdown process such that
a System::Thread would be disposed after the System instance it was
created under has been disposed, in which case doing a virtual call to
System::free with that instance would potentially cause a crash.  The
solution is to just call the C library version of free directly, since
that's all System::free does.
This commit is contained in:
Joel Dice 2012-01-12 11:00:58 -07:00
parent 7022b23b26
commit 0aa5755187
3 changed files with 24 additions and 15 deletions

View File

@ -45,6 +45,15 @@ void
join(Thread* t, Thread* o)
{
if (t != o) {
// todo: There's potentially a leak here on systems where we must
// call join on a thread in order to clean up all resources
// associated with it. If a thread has already been zombified by
// the time we get here, acquireSystem will return false, which
// means we can't safely join it because the System::Thread may
// already have been disposed. In that case, the thread has
// already exited (or will soon), but the OS will never free all
// its resources because it doesn't know we're completely done
// with it.
if (acquireSystem(t, o)) {
o->systemThread->join();
releaseSystem(t, o);

View File

@ -169,7 +169,7 @@ class MySystem: public System {
}
virtual void dispose() {
s->free(this);
::free(this);
}
pthread_t thread;
@ -197,7 +197,7 @@ class MySystem: public System {
virtual void dispose() {
pthread_mutex_destroy(&mutex);
s->free(this);
::free(this);
}
System* s;
@ -410,7 +410,7 @@ class MySystem: public System {
virtual void dispose() {
expect(s, owner_ == 0);
pthread_mutex_destroy(&mutex);
s->free(this);
::free(this);
}
System* s;
@ -441,7 +441,7 @@ class MySystem: public System {
int r UNUSED = pthread_key_delete(key);
expect(s, r == 0);
s->free(this);
::free(this);
}
System* s;
@ -468,7 +468,7 @@ class MySystem: public System {
if (start_) {
munmap(start_, length_);
}
s->free(this);
::free(this);
}
System* s;
@ -494,7 +494,7 @@ class MySystem: public System {
if (directory) {
closedir(directory);
}
s->free(this);
::free(this);
}
System* s;
@ -541,10 +541,10 @@ class MySystem: public System {
}
if (name_) {
s->free(name_);
::free(const_cast<char*>(name_));
}
s->free(this);
::free(this);
}
System* s;

View File

@ -119,7 +119,7 @@ class MySystem: public System {
CloseHandle(event);
CloseHandle(mutex);
CloseHandle(thread);
s->free(this);
::free(this);
}
HANDLE thread;
@ -150,7 +150,7 @@ class MySystem: public System {
virtual void dispose() {
CloseHandle(mutex);
s->free(this);
::free(this);
}
System* s;
@ -377,7 +377,7 @@ class MySystem: public System {
virtual void dispose() {
assert(s, owner_ == 0);
CloseHandle(mutex);
s->free(this);
::free(this);
}
System* s;
@ -408,7 +408,7 @@ class MySystem: public System {
bool r UNUSED = TlsFree(key);
assert(s, r);
s->free(this);
::free(this);
}
System* s;
@ -472,7 +472,7 @@ class MySystem: public System {
if (handle and handle != INVALID_HANDLE_VALUE) {
FindClose(handle);
}
s->free(this);
::free(this);
}
System* s;
@ -523,10 +523,10 @@ class MySystem: public System {
}
if (name_) {
s->free(name_);
::free(const_cast<char*>(name_));
}
s->free(this);
::free(this);
}
System* s;