From: Niklas Therning Date: Fri, 5 Aug 2016 17:25:39 +0000 (+0200) Subject: Merge pull request #3359 from ntherning/sgen-avoid-scanning-stack-guard-page-on-windows X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=7e92715a0fbf01d7f1b360322311aa2cb396ffaa;hp=c7aa64ab0b17e20be74cdb573e76bf871691b170;p=mono.git Merge pull request #3359 from ntherning/sgen-avoid-scanning-stack-guard-page-on-windows Prevent SGen from scanning the guard page used by Windows to dynamically grow the stack --- diff --git a/mono/metadata/sgen-mono.c b/mono/metadata/sgen-mono.c index 33e01a8fb28..5c3d772c9fa 100644 --- a/mono/metadata/sgen-mono.c +++ b/mono/metadata/sgen-mono.c @@ -2404,6 +2404,21 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p g_assert (info->client_info.stack_end); aligned_stack_start = (void*)(mword) ALIGN_TO ((mword)info->client_info.stack_start, SIZEOF_VOID_P); +#ifdef HOST_WIN32 + /* Windows uses a guard page before the committed stack memory pages to detect when the + stack needs to be grown. If we suspend a thread just after a function prolog has + decremented the stack pointer to point into the guard page but before the thread has + been able to read or write to that page, starting the stack scan at aligned_stack_start + will raise a STATUS_GUARD_PAGE_VIOLATION and the process will crash. This code uses + VirtualQuery() to determine whether stack_start points into the guard page and then + updates aligned_stack_start to point at the next non-guard page. */ + MEMORY_BASIC_INFORMATION mem_info; + SIZE_T result = VirtualQuery(info->client_info.stack_start, &mem_info, sizeof(mem_info)); + g_assert (result != 0); + if (mem_info.Protect & PAGE_GUARD) { + aligned_stack_start = ((char*) mem_info.BaseAddress) + mem_info.RegionSize; + } +#endif g_assert (info->client_info.suspend_done); SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %zd, pinned=%zd", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start, sgen_get_pinned_count ());