Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix GetThreadContext call failed in mono GC for unity 5.2.x #1294

Open
wants to merge 1 commit into
base: unity-5.2-staging
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
76 changes: 47 additions & 29 deletions libgc/win32_threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ struct GC_thread_Rep {
/* !in_use ==> stack_base == 0 */
GC_bool suspended;
GC_bool should_scan;

CONTEXT saved_context; /* populated as part of GC_suspend as */
/* resume/suspend loop may be needed for call */
/* to GetThreadContext to succeed */
# ifdef CYGWIN32
void *status; /* hold exit value until join in case it's a pointer */
pthread_t pthread_id;
Expand Down Expand Up @@ -323,34 +325,53 @@ void GC_stop_world()
while (SuspendThread(thread_table[i].handle) == (DWORD)-1)
Sleep(10);
# else
/* Apparently the Windows 95 GetOpenFileName call creates */
/* a thread that does not properly get cleaned up, and */
/* SuspendThread on its descriptor may provoke a crash. */
/* This reduces the probability of that event, though it still */
/* appears there's a race here. */
DWORD exitCode;
if (GetExitCodeThread(thread_table[i].handle,&exitCode) &&
exitCode != STILL_ACTIVE) {
thread_table[i].stack_base = 0; /* prevent stack from being pushed */
# ifndef CYGWIN32
/* this breaks pthread_join on Cygwin, which is guaranteed to */
/* only see user pthreads */
thread_table[i].in_use = FALSE;
CloseHandle(thread_table[i].handle);
# endif
continue;
}
if (SuspendThread(thread_table[i].handle) == (DWORD)-1) {
thread_table[i].stack_base = 0; /* prevent stack from being pushed */

int iterations = 0;
while (TRUE)
{
/* Apparently the Windows 95 GetOpenFileName call creates */
/* a thread that does not properly get cleaned up, and */
/* SuspendThread on its descriptor may provoke a crash. */
/* This reduces the probability of that event, though it still */
/* appears there's a race here. */
DWORD exitCode;
volatile struct GC_thread_Rep* t;
DWORD res;
if (GetExitCodeThread(thread_table[i].handle,&exitCode) &&
exitCode != STILL_ACTIVE) {
thread_table[i].stack_base = 0; /* prevent stack from being pushed */
# ifndef CYGWIN32
/* this breaks pthread_join on Cygwin, which is guaranteed to */
/* only see user pthreads */
thread_table[i].in_use = FALSE;
CloseHandle(thread_table[i].handle);
/* this breaks pthread_join on Cygwin, which is guaranteed to */
/* only see user pthreads */
thread_table[i].in_use = FALSE;
CloseHandle(thread_table[i].handle);
# endif
continue;
}

t = &thread_table[i];

do {
res = SuspendThread (t->handle);
} while (res == (DWORD)-1);

t->saved_context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
if (GetThreadContext (t->handle, &t->saved_context)) {
t->suspended = (unsigned char)TRUE;
break; /* success case break out of loop */
}

/* resume thread and try to suspend in better location */
if (ResumeThread (t->handle) == (DWORD)-1)
ABORT ("ResumeThread failed");

/* after a million tries something must be wrong */
if (iterations++ == 1000 * 1000)
ABORT ("SuspendThread loop failed");

}
# endif
thread_table[i].suspended = TRUE;
thread_table[i].suspended = TRUE;
}
# ifndef CYGWIN32
LeaveCriticalSection(&GC_write_cs);
Expand Down Expand Up @@ -437,10 +458,7 @@ void GC_push_all_stacks()
continue;
}
else {
CONTEXT context;
context.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
if (!GetThreadContext(thread_table[i].handle, &context))
ABORT("GetThreadContext failed");
CONTEXT context = thread_table[i].saved_context;

/* Push all registers that might point into the heap. Frame */
/* pointer registers are included in case client code was */
Expand Down