forked from osmocom/wireshark
Windows: Always assign newly-created processes to our job.
Move ws_pipe_kill_child_on_exit to win32-utils. Add win32_create_process, which calls CreateProcess + AssignProcessToJobObject. Use win32_create_process instead of CreateProcess everywhere. Bug: 1419 Change-Id: I7a1f17dddf6a73f6973d54621f271b69311400d1 Reviewed-on: https://code.wireshark.org/review/26448 Reviewed-by: Gerald Combs <gerald@wireshark.org> Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
0874b8bac6
commit
a2f9267615
|
@ -23,6 +23,7 @@
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <wsutil/unicode-utils.h>
|
#include <wsutil/unicode-utils.h>
|
||||||
#include <wsutil/win32-utils.h>
|
#include <wsutil/win32-utils.h>
|
||||||
|
#include <wsutil/ws_pipe.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_WAIT_H
|
#ifdef HAVE_SYS_WAIT_H
|
||||||
|
@ -219,7 +220,6 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, inf
|
||||||
HANDLE signal_pipe; /* named pipe used to send messages from parent to child (currently only stop) */
|
HANDLE signal_pipe; /* named pipe used to send messages from parent to child (currently only stop) */
|
||||||
GString *args = g_string_sized_new(200);
|
GString *args = g_string_sized_new(200);
|
||||||
gchar *quoted_arg;
|
gchar *quoted_arg;
|
||||||
gunichar2 *wcommandline;
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
|
@ -519,11 +519,10 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, inf
|
||||||
g_string_append(args, quoted_arg);
|
g_string_append(args, quoted_arg);
|
||||||
g_free(quoted_arg);
|
g_free(quoted_arg);
|
||||||
}
|
}
|
||||||
wcommandline = g_utf8_to_utf16(args->str, (glong)args->len, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
/* call dumpcap */
|
/* call dumpcap */
|
||||||
if(!CreateProcess(utf_8to16(argv[0]), wcommandline, NULL, NULL, TRUE,
|
if(!win32_create_process(argv[0], args->str, NULL, NULL, TRUE,
|
||||||
CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
||||||
report_failure("Couldn't run %s in child process: %s",
|
report_failure("Couldn't run %s in child process: %s",
|
||||||
args->str, win32strerror(GetLastError()));
|
args->str, win32strerror(GetLastError()));
|
||||||
ws_close(sync_pipe_read_fd); /* Should close sync_pipe_read */
|
ws_close(sync_pipe_read_fd); /* Should close sync_pipe_read */
|
||||||
|
@ -531,14 +530,12 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, inf
|
||||||
CloseHandle(signal_pipe);
|
CloseHandle(signal_pipe);
|
||||||
free_argv(argv, argc);
|
free_argv(argv, argc);
|
||||||
g_string_free(args, TRUE);
|
g_string_free(args, TRUE);
|
||||||
g_free(wcommandline);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
cap_session->fork_child = pi.hProcess;
|
cap_session->fork_child = pi.hProcess;
|
||||||
/* We may need to store this and close it later */
|
/* We may need to store this and close it later */
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
g_string_free(args, TRUE);
|
g_string_free(args, TRUE);
|
||||||
g_free(wcommandline);
|
|
||||||
|
|
||||||
cap_session->signal_pipe_write_fd = signal_pipe_write_fd;
|
cap_session->signal_pipe_write_fd = signal_pipe_write_fd;
|
||||||
|
|
||||||
|
@ -646,7 +643,6 @@ sync_pipe_open_command(char* const argv[], int *data_read_fd,
|
||||||
HANDLE data_pipe[2]; /* pipe used to send data from child to parent */
|
HANDLE data_pipe[2]; /* pipe used to send data from child to parent */
|
||||||
GString *args = g_string_sized_new(200);
|
GString *args = g_string_sized_new(200);
|
||||||
gchar *quoted_arg;
|
gchar *quoted_arg;
|
||||||
gunichar2 *wcommandline;
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
|
@ -752,11 +748,10 @@ sync_pipe_open_command(char* const argv[], int *data_read_fd,
|
||||||
g_string_append(args, quoted_arg);
|
g_string_append(args, quoted_arg);
|
||||||
g_free(quoted_arg);
|
g_free(quoted_arg);
|
||||||
}
|
}
|
||||||
wcommandline = g_utf8_to_utf16(args->str, (glong)args->len, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
/* call dumpcap */
|
/* call dumpcap */
|
||||||
if(!CreateProcess(utf_8to16(argv[0]), wcommandline, NULL, NULL, TRUE,
|
if(!win32_create_process(argv[0], args->str, NULL, NULL, TRUE,
|
||||||
CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
||||||
*msg = g_strdup_printf("Couldn't run %s in child process: %s",
|
*msg = g_strdup_printf("Couldn't run %s in child process: %s",
|
||||||
args->str, win32strerror(GetLastError()));
|
args->str, win32strerror(GetLastError()));
|
||||||
ws_close(*data_read_fd); /* Should close data_pipe[PIPE_READ] */
|
ws_close(*data_read_fd); /* Should close data_pipe[PIPE_READ] */
|
||||||
|
@ -764,14 +759,12 @@ sync_pipe_open_command(char* const argv[], int *data_read_fd,
|
||||||
ws_close(*message_read_fd); /* Should close sync_pipe[PIPE_READ] */
|
ws_close(*message_read_fd); /* Should close sync_pipe[PIPE_READ] */
|
||||||
CloseHandle(sync_pipe[PIPE_WRITE]);
|
CloseHandle(sync_pipe[PIPE_WRITE]);
|
||||||
g_string_free(args, TRUE);
|
g_string_free(args, TRUE);
|
||||||
g_free(wcommandline);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*fork_child = pi.hProcess;
|
*fork_child = pi.hProcess;
|
||||||
/* We may need to store this and close it later */
|
/* We may need to store this and close it later */
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
g_string_free(args, TRUE);
|
g_string_free(args, TRUE);
|
||||||
g_free(wcommandline);
|
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
/* Create a pipe for the child process to send us messages */
|
/* Create a pipe for the child process to send us messages */
|
||||||
if (pipe(sync_pipe) < 0) {
|
if (pipe(sync_pipe) < 0) {
|
||||||
|
|
|
@ -34,6 +34,9 @@ Features” section below for more details.
|
||||||
|
|
||||||
//_Non-empty section placeholder._
|
//_Non-empty section placeholder._
|
||||||
|
|
||||||
|
Dumpcap might not quit if Wireshark or TShark crashes.
|
||||||
|
(ws_buglink:1419[])
|
||||||
|
|
||||||
=== New and Updated Features
|
=== New and Updated Features
|
||||||
|
|
||||||
The following features are new (or have been significantly updated)
|
The following features are new (or have been significantly updated)
|
||||||
|
@ -172,9 +175,6 @@ locations on your system.
|
||||||
|
|
||||||
== Known Problems
|
== Known Problems
|
||||||
|
|
||||||
Dumpcap might not quit if Wireshark or TShark crashes.
|
|
||||||
(ws_buglink:1419[])
|
|
||||||
|
|
||||||
The BER dissector might infinitely loop.
|
The BER dissector might infinitely loop.
|
||||||
(ws_buglink:1516[])
|
(ws_buglink:1516[])
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <wsutil/strtoi.h>
|
#include <wsutil/strtoi.h>
|
||||||
|
#include <wsutil/win32-utils.h>
|
||||||
|
|
||||||
#include "sharkd.h"
|
#include "sharkd.h"
|
||||||
|
|
||||||
|
@ -232,7 +233,6 @@ sharkd_loop(void)
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
char *exename;
|
char *exename;
|
||||||
gunichar2 *commandline;
|
|
||||||
#endif
|
#endif
|
||||||
socket_handle_t fd;
|
socket_handle_t fd;
|
||||||
|
|
||||||
|
@ -273,11 +273,10 @@ sharkd_loop(void)
|
||||||
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
|
||||||
exename = g_strdup_printf("%s\\%s", get_progfile_dir(), "sharkd.exe");
|
exename = g_strdup_printf("%s\\%s", get_progfile_dir(), "sharkd.exe");
|
||||||
commandline = g_utf8_to_utf16("sharkd.exe -", -1, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (!CreateProcess(utf_8to16(exename), commandline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
if (!win32_create_process(exename, "sharkd.exe -", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "CreateProcess(%s) failed\n", exename);
|
fprintf(stderr, "win32_create_process(%s) failed\n", exename);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -285,7 +284,6 @@ sharkd_loop(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(exename);
|
g_free(exename);
|
||||||
g_free(commandline);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
closesocket(fd);
|
closesocket(fd);
|
||||||
|
|
|
@ -8,8 +8,14 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
#include "win32-utils.h"
|
#include "win32-utils.h"
|
||||||
|
|
||||||
|
#include <log.h>
|
||||||
|
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
/* Quote the argument element if necessary, so that it will get
|
/* Quote the argument element if necessary, so that it will get
|
||||||
* reconstructed correctly in the C runtime startup code. Note that
|
* reconstructed correctly in the C runtime startup code. Note that
|
||||||
* the unquoting algorithm in the C runtime is really weird, and
|
* the unquoting algorithm in the C runtime is really weird, and
|
||||||
|
@ -149,15 +155,78 @@ win32strexception(DWORD exception)
|
||||||
return errbuf;
|
return errbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This appears to be the closest equivalent to SIGPIPE on Windows.
|
||||||
|
// https://blogs.msdn.microsoft.com/oldnewthing/20131209-00/?p=2433
|
||||||
|
// https://stackoverflow.com/a/53214/82195
|
||||||
|
|
||||||
|
static void win32_kill_child_on_exit(HANDLE child_handle) {
|
||||||
|
static HANDLE cjo_handle = NULL;
|
||||||
|
if (!cjo_handle) {
|
||||||
|
cjo_handle = CreateJobObject(NULL, _T("Local\\Wireshark child process cleanup"));
|
||||||
|
|
||||||
|
if (!cjo_handle) {
|
||||||
|
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create child cleanup job object: %s",
|
||||||
|
win32strerror(GetLastError()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JOBOBJECT_EXTENDED_LIMIT_INFORMATION cjo_jel_info = { 0 };
|
||||||
|
cjo_jel_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||||
|
BOOL sijo_ret = SetInformationJobObject(cjo_handle, JobObjectExtendedLimitInformation,
|
||||||
|
&cjo_jel_info, sizeof(cjo_jel_info));
|
||||||
|
if (!sijo_ret) {
|
||||||
|
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not set child cleanup limits: %s",
|
||||||
|
win32strerror(GetLastError()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL aptjo_ret = AssignProcessToJobObject(cjo_handle, child_handle);
|
||||||
|
if (!aptjo_ret) {
|
||||||
|
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not assign child cleanup process: %s",
|
||||||
|
win32strerror(GetLastError()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL win32_create_process(const char *application_name, const char *command_line, LPSECURITY_ATTRIBUTES process_attributes, LPSECURITY_ATTRIBUTES thread_attributes, BOOL inherit_handles, DWORD creation_flags, LPVOID environment, const char *current_directory, LPSTARTUPINFO startup_info, LPPROCESS_INFORMATION process_information)
|
||||||
|
{
|
||||||
|
gunichar2 *wappname = NULL, *wcurrentdirectory = NULL;
|
||||||
|
gunichar2 *wcommandline = g_utf8_to_utf16(command_line, -1, NULL, NULL, NULL);
|
||||||
|
// CREATE_SUSPENDED: Suspend the child so that we can cleanly call
|
||||||
|
// AssignProcessToJobObject.
|
||||||
|
// CREATE_BREAKAWAY_FROM_JOB: The main application might be associated with
|
||||||
|
// a job, e.g. if we're running from ConEmu or Visual Studio. Break away
|
||||||
|
// from it so that we can cleanly call AssignProcessToJobObject on *our* job.
|
||||||
|
DWORD wcreationflags = creation_flags|CREATE_SUSPENDED|CREATE_BREAKAWAY_FROM_JOB;
|
||||||
|
|
||||||
|
if (application_name) {
|
||||||
|
wappname = g_utf8_to_utf16(application_name, -1, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
if (current_directory) {
|
||||||
|
wcurrentdirectory = g_utf8_to_utf16(current_directory, -1, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
BOOL cp_res = CreateProcess(wappname, wcommandline, process_attributes, thread_attributes,
|
||||||
|
inherit_handles, wcreationflags, environment, wcurrentdirectory, startup_info,
|
||||||
|
process_information);
|
||||||
|
if (cp_res) {
|
||||||
|
win32_kill_child_on_exit(process_information->hProcess);
|
||||||
|
ResumeThread(process_information->hThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(wappname);
|
||||||
|
g_free(wcommandline);
|
||||||
|
g_free(wcurrentdirectory);
|
||||||
|
return cp_res;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||||
*
|
*
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* c-basic-offset: 2
|
* c-basic-offset: 4
|
||||||
* tab-width: 8
|
* tab-width: 8
|
||||||
* indent-tabs-mode: nil
|
* indent-tabs-mode: nil
|
||||||
* End:
|
* End:
|
||||||
*
|
*
|
||||||
* ex: set shiftwidth=2 tabstop=8 expandtab:
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||||
* :indentSize=2:tabSize=8:noTabs=true:
|
* :indentSize=4:tabSize=8:noTabs=true:
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -64,6 +64,28 @@ const char * win32strerror(DWORD error);
|
||||||
WS_DLL_PUBLIC
|
WS_DLL_PUBLIC
|
||||||
const char * win32strexception(DWORD exception);
|
const char * win32strexception(DWORD exception);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ws_pipe_create_process Create a process and assign it to the main application
|
||||||
|
* job object so that it will be killed the the main application exits.
|
||||||
|
* @param application_name Application name. Will be converted to its UTF-16 equivalent or NULL.
|
||||||
|
* @param command_line Command line. Will be converted to its UTF-16 equivalent.
|
||||||
|
* @param process_attributes Same as CreateProcess.
|
||||||
|
* @param thread_attributes Same as CreateProcess.
|
||||||
|
* @param inherit_handles Same as CreateProcess.
|
||||||
|
* @param creation_flags Will be ORed with CREATE_SUSPENDED|CREATE_BREAKAWAY_FROM_JOB.
|
||||||
|
* @param environment Same as CreateProcess.
|
||||||
|
* @param current_directory Current directory. Will be converted to its UTF-16 equivalent or NULL.
|
||||||
|
* @param startup_info Same as CreateProcess.
|
||||||
|
* @param process_information Same as CreateProcess.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
WS_DLL_PUBLIC
|
||||||
|
BOOL win32_create_process(const char *application_name, const char *command_line,
|
||||||
|
LPSECURITY_ATTRIBUTES process_attributes, LPSECURITY_ATTRIBUTES thread_attributes,
|
||||||
|
BOOL inherit_handles, DWORD creation_flags, LPVOID environment,
|
||||||
|
const char *current_directory, LPSTARTUPINFO startup_info, LPPROCESS_INFORMATION process_information
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,54 +33,6 @@
|
||||||
#include "wsutil/filesystem.h"
|
#include "wsutil/filesystem.h"
|
||||||
#include "wsutil/ws_pipe.h"
|
#include "wsutil/ws_pipe.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <tchar.h>
|
|
||||||
#include "wsutil/win32-utils.h"
|
|
||||||
|
|
||||||
// This appears to be the closest equivalent to SIGPIPE on Windows.
|
|
||||||
// https://blogs.msdn.microsoft.com/oldnewthing/20131209-00/?p=2433
|
|
||||||
// https://stackoverflow.com/a/53214/82195
|
|
||||||
// We might want to make it public and use it for our other external
|
|
||||||
// processes.
|
|
||||||
|
|
||||||
// CreateProcess flags.
|
|
||||||
// CREATE_NEW_CONSOLE: Don't interfere with the main application console.
|
|
||||||
// CREATE_SUSPENDED: Suspend the child so that we can cleanly call
|
|
||||||
// AssignProcessToJobObject.
|
|
||||||
// CREATE_BREAKAWAY_FROM_JOB: The main application might be associated with
|
|
||||||
// a job, e.g. if we're running from ConEmu or Visual Studio. Break away
|
|
||||||
// from it so that we can cleanly call AssignProcessToJobObject on *our* job.
|
|
||||||
#define WS_CP_JOB_FLAGS (CREATE_NEW_CONSOLE|CREATE_SUSPENDED|CREATE_BREAKAWAY_FROM_JOB)
|
|
||||||
|
|
||||||
static void ws_pipe_kill_child_on_exit(ws_pipe_handle child_handle) {
|
|
||||||
static HANDLE cjo_handle = NULL;
|
|
||||||
if (!cjo_handle) {
|
|
||||||
cjo_handle = CreateJobObject(NULL, _T("Local\\Wireshark child process cleanup"));
|
|
||||||
|
|
||||||
if (!cjo_handle) {
|
|
||||||
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create child cleanup job object: %s",
|
|
||||||
win32strerror(GetLastError()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION cjo_jel_info = { 0 };
|
|
||||||
cjo_jel_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
|
||||||
BOOL sijo_ret = SetInformationJobObject(cjo_handle, JobObjectExtendedLimitInformation,
|
|
||||||
&cjo_jel_info, sizeof(cjo_jel_info));
|
|
||||||
if (!sijo_ret) {
|
|
||||||
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not set child cleanup limits: %s",
|
|
||||||
win32strerror(GetLastError()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL aptjo_ret = AssignProcessToJobObject(cjo_handle, child_handle);
|
|
||||||
if (!aptjo_ret) {
|
|
||||||
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not assign child cleanup process: %s",
|
|
||||||
win32strerror(GetLastError()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
gboolean ws_pipe_spawn_sync(gchar *dirname, gchar *command, gint argc, gchar **args, gchar **command_output)
|
gboolean ws_pipe_spawn_sync(gchar *dirname, gchar *command, gint argc, gchar **args, gchar **command_output)
|
||||||
{
|
{
|
||||||
gboolean status = FALSE;
|
gboolean status = FALSE;
|
||||||
|
@ -94,7 +46,6 @@ gboolean ws_pipe_spawn_sync(gchar *dirname, gchar *command, gint argc, gchar **a
|
||||||
|
|
||||||
GString *winargs = g_string_sized_new(200);
|
GString *winargs = g_string_sized_new(200);
|
||||||
gchar *quoted_arg;
|
gchar *quoted_arg;
|
||||||
gunichar2 *wcommandline;
|
|
||||||
|
|
||||||
STARTUPINFO info;
|
STARTUPINFO info;
|
||||||
PROCESS_INFORMATION processInfo;
|
PROCESS_INFORMATION processInfo;
|
||||||
|
@ -158,8 +109,6 @@ gboolean ws_pipe_spawn_sync(gchar *dirname, gchar *command, gint argc, gchar **a
|
||||||
g_free(quoted_arg);
|
g_free(quoted_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
wcommandline = g_utf8_to_utf16(winargs->str, (glong)winargs->len, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
||||||
memset(&info, 0, sizeof(STARTUPINFO));
|
memset(&info, 0, sizeof(STARTUPINFO));
|
||||||
|
|
||||||
|
@ -169,12 +118,10 @@ gboolean ws_pipe_spawn_sync(gchar *dirname, gchar *command, gint argc, gchar **a
|
||||||
info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||||
info.wShowWindow = SW_HIDE;
|
info.wShowWindow = SW_HIDE;
|
||||||
|
|
||||||
if (CreateProcess(NULL, wcommandline, NULL, NULL, TRUE, WS_CP_JOB_FLAGS, NULL, NULL, &info, &processInfo))
|
if (win32_create_process(NULL, winargs->str, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &info, &processInfo))
|
||||||
{
|
{
|
||||||
gchar* buffer;
|
gchar* buffer;
|
||||||
|
|
||||||
ws_pipe_kill_child_on_exit(processInfo.hProcess);
|
|
||||||
ResumeThread(processInfo.hThread);
|
|
||||||
WaitForSingleObject(processInfo.hProcess, INFINITE);
|
WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||||
buffer = (gchar*)g_malloc(BUFFER_SIZE);
|
buffer = (gchar*)g_malloc(BUFFER_SIZE);
|
||||||
status = ws_read_string_from_pipe(child_stdout_rd, buffer, BUFFER_SIZE);
|
status = ws_read_string_from_pipe(child_stdout_rd, buffer, BUFFER_SIZE);
|
||||||
|
@ -237,7 +184,6 @@ GPid ws_pipe_spawn_async(ws_pipe_t *ws_pipe, GPtrArray *args)
|
||||||
|
|
||||||
GString *winargs = g_string_sized_new(200);
|
GString *winargs = g_string_sized_new(200);
|
||||||
gchar *quoted_arg;
|
gchar *quoted_arg;
|
||||||
gunichar2 *wcommandline;
|
|
||||||
|
|
||||||
STARTUPINFO info;
|
STARTUPINFO info;
|
||||||
PROCESS_INFORMATION processInfo;
|
PROCESS_INFORMATION processInfo;
|
||||||
|
@ -290,8 +236,6 @@ GPid ws_pipe_spawn_async(ws_pipe_t *ws_pipe, GPtrArray *args)
|
||||||
g_free(quoted_arg);
|
g_free(quoted_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
wcommandline = g_utf8_to_utf16(winargs->str, (glong)winargs->len, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
|
||||||
memset(&info, 0, sizeof(STARTUPINFO));
|
memset(&info, 0, sizeof(STARTUPINFO));
|
||||||
|
|
||||||
|
@ -302,10 +246,8 @@ GPid ws_pipe_spawn_async(ws_pipe_t *ws_pipe, GPtrArray *args)
|
||||||
info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||||
info.wShowWindow = SW_HIDE;
|
info.wShowWindow = SW_HIDE;
|
||||||
|
|
||||||
if (CreateProcess(NULL, wcommandline, NULL, NULL, TRUE, WS_CP_JOB_FLAGS, NULL, NULL, &info, &processInfo))
|
if (win32_create_process(NULL, winargs->str, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &info, &processInfo))
|
||||||
{
|
{
|
||||||
ws_pipe_kill_child_on_exit(processInfo.hProcess);
|
|
||||||
ResumeThread(processInfo.hThread);
|
|
||||||
ws_pipe->stdin_fd = _open_osfhandle((intptr_t)(child_stdin_wr), _O_BINARY);
|
ws_pipe->stdin_fd = _open_osfhandle((intptr_t)(child_stdin_wr), _O_BINARY);
|
||||||
ws_pipe->stdout_fd = _open_osfhandle((intptr_t)(child_stdout_rd), _O_BINARY);
|
ws_pipe->stdout_fd = _open_osfhandle((intptr_t)(child_stdout_rd), _O_BINARY);
|
||||||
ws_pipe->stderr_fd = _open_osfhandle((intptr_t)(child_stderr_rd), _O_BINARY);
|
ws_pipe->stderr_fd = _open_osfhandle((intptr_t)(child_stderr_rd), _O_BINARY);
|
||||||
|
|
|
@ -73,6 +73,7 @@ static inline gboolean ws_pipe_valid(ws_pipe_t *ws_pipe)
|
||||||
*/
|
*/
|
||||||
WS_DLL_PUBLIC GPid ws_pipe_spawn_async (ws_pipe_t * ws_pipe, GPtrArray * args );
|
WS_DLL_PUBLIC GPid ws_pipe_spawn_async (ws_pipe_t * ws_pipe, GPtrArray * args );
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
/**
|
/**
|
||||||
* @brief Wait for a set of handles using WaitForMultipleObjects. Windows only.
|
* @brief Wait for a set of handles using WaitForMultipleObjects. Windows only.
|
||||||
* @param pipe_handles An array of handles
|
* @param pipe_handles An array of handles
|
||||||
|
@ -80,7 +81,6 @@ WS_DLL_PUBLIC GPid ws_pipe_spawn_async (ws_pipe_t * ws_pipe, GPtrArray * args );
|
||||||
* @param pid Child process PID.
|
* @param pid Child process PID.
|
||||||
* @return TRUE on success or FALSE on failure.
|
* @return TRUE on success or FALSE on failure.
|
||||||
*/
|
*/
|
||||||
#ifdef _WIN32
|
|
||||||
WS_DLL_PUBLIC gboolean ws_pipe_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid);
|
WS_DLL_PUBLIC gboolean ws_pipe_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue