aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/fhandler/process.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler/process.cc')
-rw-r--r--winsup/cygwin/fhandler/process.cc33
1 files changed, 30 insertions, 3 deletions
diff --git a/winsup/cygwin/fhandler/process.cc b/winsup/cygwin/fhandler/process.cc
index 8fae9be..e00cae5 100644
--- a/winsup/cygwin/fhandler/process.cc
+++ b/winsup/cygwin/fhandler/process.cc
@@ -621,14 +621,39 @@ struct heap_info
: heap_vm_chunks (NULL)
{
PDEBUG_BUFFER buf;
+ wchar_t mtx_name [32];
+ HANDLE mtx;
NTSTATUS status;
PDEBUG_HEAP_ARRAY harray;
+ /* We need a global mutex here, because RtlQueryProcessDebugInformation
+ is neither thread-safe, nor multi-process-safe. If it's called in
+ parallel on the same process it can crash that process. We can't
+ avoid this if a non-Cygwin app calls RtlQueryProcessDebugInformation
+ on the same process in parallel, but we can avoid Cygwin processes
+ crashing process PID just because they open /proc/PID/maps in parallel
+ by serializing RtlQueryProcessDebugInformation on the same process.
+
+ Note that the mutex guards the entire code from
+ RtlCreateQueryDebugBuffer to RtlDestroyQueryDebugBuffer including the
+ code accessing the debug buffer. Apparently the debug buffer needs
+ safeguarded against parallel access all the time it's used!!! */
+ __small_swprintf (mtx_name, L"cyg-heapinfo-mtx-%u", pid);
+ mtx = CreateMutexW (&sec_none_nih, FALSE, mtx_name);
+ if (!mtx)
+ return;
+ WaitForSingleObject (mtx, INFINITE);
buf = RtlCreateQueryDebugBuffer (16 * 65536, FALSE);
+ if (buf)
+ status = RtlQueryProcessDebugInformation (pid,
+ PDI_HEAPS | PDI_HEAP_BLOCKS,
+ buf);
if (!buf)
- return;
- status = RtlQueryProcessDebugInformation (pid, PDI_HEAPS | PDI_HEAP_BLOCKS,
- buf);
+ {
+ ReleaseMutex (mtx);
+ CloseHandle (mtx);
+ return;
+ }
if (NT_SUCCESS (status)
&& (harray = (PDEBUG_HEAP_ARRAY) buf->HeapInformation) != NULL)
for (ULONG hcnt = 0; hcnt < harray->Count; ++hcnt)
@@ -653,6 +678,8 @@ struct heap_info
}
}
RtlDestroyQueryDebugBuffer (buf);
+ ReleaseMutex (mtx);
+ CloseHandle (mtx);
}
char *fill_if_match (char *base, ULONG type, char *dest)