Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -15138,7 +15138,7 @@ fi

case $host_os in
mingw*)
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -lsecur32 -luserenv -luser32"
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -lsecur32 -luserenv -luser32 -ldbghelp -lole32 -luuid"
;;
esac
case $host_os in
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ AM_CONDITIONAL([OS400], [AS_CASE([$host_os],[os400], [true], [false])
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
AS_CASE([$host_os],[mingw*], [
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -lsecur32 -luserenv -luser32"
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -lsecur32 -luserenv -luser32 -ldbghelp -lole32 -luuid"
])
AS_CASE([$host_os], [netbsd*], [AC_CHECK_LIB([kvm], [kvm_open])])
AS_CASE([$host_os], [kfreebsd*], [
Expand Down
1 change: 1 addition & 0 deletions include/uv/win.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ typedef intptr_t ssize_t;
/* Signals supported by uv_signal and or uv_kill */
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGABRT_COMPAT 6
#define SIGFPE 8
Expand Down
112 changes: 112 additions & 0 deletions src/win/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#include "internal.h"
#include "handle-inl.h"
#include "req-inl.h"
#include <dbghelp.h>
#include <shlobj.h>
#include <psapi.h> /* GetModuleBaseNameW */


typedef struct env_var {
Expand Down Expand Up @@ -1250,7 +1253,116 @@ static int uv__kill(HANDLE process_handle, int signum) {
return UV_EINVAL;
}

/* Create a dump file for the targeted process, if the registry key
* `HKLM:Software\Microsoft\Windows\Windows Error Reporting\LocalDumps`
* exists. The location of the dumps can be influenced by the `DumpFolder`
* sub-key, which has a default value of `%LOCALAPPDATA%\CrashDumps`, see [0]
* for more detail. Note that if the dump folder does not exist, we attempt
* to create it, to match behavior with WER itself.
* [0]: https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps */
if (signum == SIGQUIT) {
HKEY registry_key;
DWORD pid, ret;
WCHAR basename[MAX_PATH];

/* Get target process name. */
GetModuleBaseNameW(process_handle, NULL, &basename[0], sizeof(basename));

/* Get PID of target process. */
pid = GetProcessId(process_handle);

/* Get LocalDumps directory path. */
ret = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps",
0,
KEY_QUERY_VALUE,
&registry_key);
if (ret == ERROR_SUCCESS) {
HANDLE hDumpFile = NULL;
WCHAR dump_folder[MAX_PATH], dump_name[MAX_PATH];
DWORD dump_folder_len = sizeof(dump_folder), key_type = 0;
ret = RegGetValueW(registry_key,
NULL,
L"DumpFolder",
RRF_RT_ANY,
&key_type,
(PVOID) dump_folder,
&dump_folder_len);
if (ret != ERROR_SUCCESS) {
/* Default value for `dump_folder` is `%LOCALAPPDATA%\CrashDumps`. */
WCHAR* localappdata;
SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, NULL, &localappdata);
_snwprintf_s(dump_folder,
sizeof(dump_folder),
_TRUNCATE,
L"%ls\\CrashDumps",
localappdata);
CoTaskMemFree(localappdata);
}
RegCloseKey(registry_key);

/* Create dump folder if it doesn't already exist. */
CreateDirectoryW(dump_folder, NULL);

/* Construct dump filename from process name and PID. */
_snwprintf_s(dump_name,
sizeof(dump_name),
_TRUNCATE,
L"%ls\\%ls.%d.dmp",
dump_folder,
basename,
pid);

hDumpFile = CreateFileW(dump_name,
GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hDumpFile != INVALID_HANDLE_VALUE) {
DWORD dump_options, sym_options;
FILE_DISPOSITION_INFO DeleteOnClose = { TRUE };

/* If something goes wrong while writing it out, delete the file. */
SetFileInformationByHandle(hDumpFile,
FileDispositionInfo,
&DeleteOnClose,
sizeof(DeleteOnClose));

/* Tell wine to dump ELF modules as well. */
sym_options = SymGetOptions();
SymSetOptions(sym_options | 0x40000000);

/* We default to a fairly complete dump. In the future, we may want to
* allow clients to customize what kind of dump to create. */
dump_options = MiniDumpWithFullMemory |
MiniDumpIgnoreInaccessibleMemory |
MiniDumpWithAvxXStateContext;

if (MiniDumpWriteDump(process_handle,
pid,
hDumpFile,
dump_options,
NULL,
NULL,
NULL)) {
/* Don't delete the file on close if we successfully wrote it out. */
FILE_DISPOSITION_INFO DontDeleteOnClose = { FALSE };
SetFileInformationByHandle(hDumpFile,
FileDispositionInfo,
&DontDeleteOnClose,
sizeof(DontDeleteOnClose));
}
SymSetOptions(sym_options);
CloseHandle(hDumpFile);
}
}
}

switch (signum) {
case SIGQUIT:
case SIGTERM:
case SIGKILL:
case SIGINT: {
Expand Down