+2002-11-18 Tor Lillqvist <tml@iki.fi>
+
+ [Win32] Fix the asynchronous g_spawn* to return the process handle
+ of the started program properly. (Note: not the process id. The
+ spawn*() functions in the C runtime return the created process's
+ handle. There doesn't seem to be any way to get the process id of
+ a child process if you have the handle. But then, the process
+ handle usually is more useful anyway.)
+
+ * glib/gspawn-win32-helper.c (WinMain): If the spawning of the
+ child process succeeded, and if asynchronous spawn (P_NOWAIT),
+ write the result handle up to the parent process, waiting to read
+ it in do_spawn_with_pipes().
+
+ * glib/gspawn-win32.c (do_spawn): Use return value from spawning
+ the helper. If it is -1 the helper wasn't found or couldn't be run
+ for some reason. Otherwise it is the helper's process handle.
+
+ (g_spawn_async_with_pipes): Pass the child_pid parameter on to
+ do_spawn_with_pipes().
+
+ (do_spawn_with_pipes): Take also a child_pid parameter. If
+ do_spawn() returned -1, fail immediately. Otherwise make the
+ handle passed to us by the helper process into a handle valid in
+ this process by calling DuplicateHandle().
+
2002-11-17 Tor Lillqvist <tml@iki.fi>
* glib/gspawn-win32.c (g_spawn_async_with_pipes): Ignore the
+2002-11-18 Tor Lillqvist <tml@iki.fi>
+
+ [Win32] Fix the asynchronous g_spawn* to return the process handle
+ of the started program properly. (Note: not the process id. The
+ spawn*() functions in the C runtime return the created process's
+ handle. There doesn't seem to be any way to get the process id of
+ a child process if you have the handle. But then, the process
+ handle usually is more useful anyway.)
+
+ * glib/gspawn-win32-helper.c (WinMain): If the spawning of the
+ child process succeeded, and if asynchronous spawn (P_NOWAIT),
+ write the result handle up to the parent process, waiting to read
+ it in do_spawn_with_pipes().
+
+ * glib/gspawn-win32.c (do_spawn): Use return value from spawning
+ the helper. If it is -1 the helper wasn't found or couldn't be run
+ for some reason. Otherwise it is the helper's process handle.
+
+ (g_spawn_async_with_pipes): Pass the child_pid parameter on to
+ do_spawn_with_pipes().
+
+ (do_spawn_with_pipes): Take also a child_pid parameter. If
+ do_spawn() returned -1, fail immediately. Otherwise make the
+ handle passed to us by the helper process into a handle valid in
+ this process by calling DuplicateHandle().
+
2002-11-17 Tor Lillqvist <tml@iki.fi>
* glib/gspawn-win32.c (g_spawn_async_with_pipes): Ignore the
+2002-11-18 Tor Lillqvist <tml@iki.fi>
+
+ [Win32] Fix the asynchronous g_spawn* to return the process handle
+ of the started program properly. (Note: not the process id. The
+ spawn*() functions in the C runtime return the created process's
+ handle. There doesn't seem to be any way to get the process id of
+ a child process if you have the handle. But then, the process
+ handle usually is more useful anyway.)
+
+ * glib/gspawn-win32-helper.c (WinMain): If the spawning of the
+ child process succeeded, and if asynchronous spawn (P_NOWAIT),
+ write the result handle up to the parent process, waiting to read
+ it in do_spawn_with_pipes().
+
+ * glib/gspawn-win32.c (do_spawn): Use return value from spawning
+ the helper. If it is -1 the helper wasn't found or couldn't be run
+ for some reason. Otherwise it is the helper's process handle.
+
+ (g_spawn_async_with_pipes): Pass the child_pid parameter on to
+ do_spawn_with_pipes().
+
+ (do_spawn_with_pipes): Take also a child_pid parameter. If
+ do_spawn() returned -1, fail immediately. Otherwise make the
+ handle passed to us by the helper process into a handle valid in
+ this process by calling DuplicateHandle().
+
2002-11-17 Tor Lillqvist <tml@iki.fi>
* glib/gspawn-win32.c (g_spawn_async_with_pipes): Ignore the
+2002-11-18 Tor Lillqvist <tml@iki.fi>
+
+ [Win32] Fix the asynchronous g_spawn* to return the process handle
+ of the started program properly. (Note: not the process id. The
+ spawn*() functions in the C runtime return the created process's
+ handle. There doesn't seem to be any way to get the process id of
+ a child process if you have the handle. But then, the process
+ handle usually is more useful anyway.)
+
+ * glib/gspawn-win32-helper.c (WinMain): If the spawning of the
+ child process succeeded, and if asynchronous spawn (P_NOWAIT),
+ write the result handle up to the parent process, waiting to read
+ it in do_spawn_with_pipes().
+
+ * glib/gspawn-win32.c (do_spawn): Use return value from spawning
+ the helper. If it is -1 the helper wasn't found or couldn't be run
+ for some reason. Otherwise it is the helper's process handle.
+
+ (g_spawn_async_with_pipes): Pass the child_pid parameter on to
+ do_spawn_with_pipes().
+
+ (do_spawn_with_pipes): Take also a child_pid parameter. If
+ do_spawn() returned -1, fail immediately. Otherwise make the
+ handle passed to us by the helper process into a handle valid in
+ this process by calling DuplicateHandle().
+
2002-11-17 Tor Lillqvist <tml@iki.fi>
* glib/gspawn-win32.c (g_spawn_async_with_pipes): Ignore the
+2002-11-18 Tor Lillqvist <tml@iki.fi>
+
+ [Win32] Fix the asynchronous g_spawn* to return the process handle
+ of the started program properly. (Note: not the process id. The
+ spawn*() functions in the C runtime return the created process's
+ handle. There doesn't seem to be any way to get the process id of
+ a child process if you have the handle. But then, the process
+ handle usually is more useful anyway.)
+
+ * glib/gspawn-win32-helper.c (WinMain): If the spawning of the
+ child process succeeded, and if asynchronous spawn (P_NOWAIT),
+ write the result handle up to the parent process, waiting to read
+ it in do_spawn_with_pipes().
+
+ * glib/gspawn-win32.c (do_spawn): Use return value from spawning
+ the helper. If it is -1 the helper wasn't found or couldn't be run
+ for some reason. Otherwise it is the helper's process handle.
+
+ (g_spawn_async_with_pipes): Pass the child_pid parameter on to
+ do_spawn_with_pipes().
+
+ (do_spawn_with_pipes): Take also a child_pid parameter. If
+ do_spawn() returned -1, fail immediately. Otherwise make the
+ handle passed to us by the helper process into a handle valid in
+ this process by calling DuplicateHandle().
+
2002-11-17 Tor Lillqvist <tml@iki.fi>
* glib/gspawn-win32.c (g_spawn_async_with_pipes): Ignore the
+2002-11-18 Tor Lillqvist <tml@iki.fi>
+
+ [Win32] Fix the asynchronous g_spawn* to return the process handle
+ of the started program properly. (Note: not the process id. The
+ spawn*() functions in the C runtime return the created process's
+ handle. There doesn't seem to be any way to get the process id of
+ a child process if you have the handle. But then, the process
+ handle usually is more useful anyway.)
+
+ * glib/gspawn-win32-helper.c (WinMain): If the spawning of the
+ child process succeeded, and if asynchronous spawn (P_NOWAIT),
+ write the result handle up to the parent process, waiting to read
+ it in do_spawn_with_pipes().
+
+ * glib/gspawn-win32.c (do_spawn): Use return value from spawning
+ the helper. If it is -1 the helper wasn't found or couldn't be run
+ for some reason. Otherwise it is the helper's process handle.
+
+ (g_spawn_async_with_pipes): Pass the child_pid parameter on to
+ do_spawn_with_pipes().
+
+ (do_spawn_with_pipes): Take also a child_pid parameter. If
+ do_spawn() returned -1, fail immediately. Otherwise make the
+ handle passed to us by the helper process into a handle valid in
+ this process by calling DuplicateHandle().
+
2002-11-17 Tor Lillqvist <tml@iki.fi>
* glib/gspawn-win32.c (g_spawn_async_with_pipes): Ignore the
+2002-11-18 Tor Lillqvist <tml@iki.fi>
+
+ [Win32] Fix the asynchronous g_spawn* to return the process handle
+ of the started program properly. (Note: not the process id. The
+ spawn*() functions in the C runtime return the created process's
+ handle. There doesn't seem to be any way to get the process id of
+ a child process if you have the handle. But then, the process
+ handle usually is more useful anyway.)
+
+ * glib/gspawn-win32-helper.c (WinMain): If the spawning of the
+ child process succeeded, and if asynchronous spawn (P_NOWAIT),
+ write the result handle up to the parent process, waiting to read
+ it in do_spawn_with_pipes().
+
+ * glib/gspawn-win32.c (do_spawn): Use return value from spawning
+ the helper. If it is -1 the helper wasn't found or couldn't be run
+ for some reason. Otherwise it is the helper's process handle.
+
+ (g_spawn_async_with_pipes): Pass the child_pid parameter on to
+ do_spawn_with_pipes().
+
+ (do_spawn_with_pipes): Take also a child_pid parameter. If
+ do_spawn() returned -1, fail immediately. Otherwise make the
+ handle passed to us by the helper process into a handle valid in
+ this process by calling DuplicateHandle().
+
2002-11-17 Tor Lillqvist <tml@iki.fi>
* glib/gspawn-win32.c (g_spawn_async_with_pipes): Ignore the
int i;
int fd;
int mode;
- gint zero = 0;
+ int handle;
+ int no_error = CHILD_NO_ERROR;
+ int zero = 0;
SETUP_DEBUG();
{
debugstring = g_string_new ("");
g_string_append (debugstring,
- g_strdup_printf ("calling %s on program %s, __argv: ",
+ g_strdup_printf ("calling %s %s mode=%s argv: ",
(__argv[ARG_USE_PATH][0] == 'y' ?
"spawnvp" : "spawnv"),
- __argv[ARG_PROGRAM]));
+ __argv[ARG_PROGRAM],
+ (mode == P_WAIT ?
+ "P_WAIT" : "P_NOWAIT")));
i = ARG_PROGRAM+1;
while (__argv[i])
{
}
if (__argv[ARG_USE_PATH][0] == 'y')
- {
- if (spawnvp (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM) < 0)
- write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
- }
+ handle = spawnvp (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM);
else
+ handle = spawnv (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM);
+
+ if (debug)
{
- if (spawnv (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM) < 0)
- write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
+ debugstring = g_string_new ("");
+ g_string_append (debugstring,
+ g_strdup_printf ("%s returned %#x",
+ (__argv[ARG_USE_PATH][0] == 'y' ?
+ "spawnvp" : "spawnv"),
+ handle));
+ MessageBox (NULL, debugstring->str, "gspawn-win32-helper", 0);
}
- write (child_err_report_fd, &zero, sizeof (zero));
- write (child_err_report_fd, &zero, sizeof (zero));
+
+ if (handle < 0)
+ write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
+
+ write (child_err_report_fd, &no_error, sizeof (no_error));
+ if (mode == P_NOWAIT)
+ write (child_err_report_fd, &handle, sizeof (handle));
+ else
+ write (child_err_report_fd, &zero, sizeof (zero));
return 0;
}
gboolean child_inherits_stdin,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
+ gint *child_pid,
gint *standard_input,
gint *standard_output,
gint *standard_error,
{
gint outpipe = -1;
gint errpipe = -1;
+ gint pid;
GIOChannel *outchannel = NULL;
GIOChannel *errchannel = NULL;
GPollFD outfd, errfd;
(flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
child_setup,
user_data,
+ &pid,
NULL,
standard_output ? &outpipe : NULL,
standard_error ? &errpipe : NULL,
(flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
child_setup,
user_data,
+ child_pid,
standard_input,
standard_output,
standard_error,
gchar **new_argv;
gchar args[ARG_COUNT][10];
gint i;
+ int rc;
int argc = 0;
SETUP_DEBUG();
}
if (working_directory && *working_directory)
- new_argv[ARG_WORKING_DIRECTORY] = working_directory;
+ new_argv[ARG_WORKING_DIRECTORY] = g_strdup (working_directory);
else
new_argv[ARG_WORKING_DIRECTORY] = "-";
/* Let's hope envp hasn't mucked with PATH so that
* gspawn-win32-helper.exe isn't found.
*/
- spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
+ rc = spawnvpe (P_NOWAIT, "gspawn-win32-helper", new_argv, envp);
else
- spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
-
- /* FIXME: What if gspawn-win32-helper.exe isn't found? */
+ rc = spawnvp (P_NOWAIT, "gspawn-win32-helper", new_argv);
/* Close the child_err_report_fd and the other process's ends of the
* pipes in this process, otherwise the reader will never get
if (stderr_fd >= 0)
close (stderr_fd);
+ g_free (new_argv[ARG_WORKING_DIRECTORY]);
g_free (new_argv);
- return 0;
+ return rc;
}
static gboolean
gboolean child_inherits_stdin,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
+ gint *child_pid,
gint *standard_input,
gint *standard_output,
gint *standard_error,
gint stdout_pipe[2] = { -1, -1 };
gint stderr_pipe[2] = { -1, -1 };
gint child_err_report_pipe[2] = { -1, -1 };
- gint status;
+ gint helper = -1;
gint buf[2];
gint n_ints = 0;
if (standard_error && !make_pipe (stderr_pipe, error))
goto cleanup_and_fail;
- status = do_spawn (dont_wait,
+ helper = do_spawn (dont_wait,
child_err_report_pipe[1],
stdin_pipe[0],
stdout_pipe[1],
child_setup,
user_data);
+ /* do_spawn() returns -1 if gspawn-win32-helper couldn't be run */
+ if (helper == -1)
+ {
+ g_set_error (error,
+ G_SPAWN_ERROR,
+ G_SPAWN_ERROR_FAILED,
+ _("Failed to execute helper program"));
+ goto cleanup_and_fail;
+ }
+
if (!read_ints (child_err_report_pipe[0],
buf, 2, &n_ints,
- error))
+ error) ||
+ n_ints != 2)
goto cleanup_and_fail;
- if (n_ints == 2)
+ /* Error code from gspawn-win32-helper. */
+ switch (buf[0])
{
- /* Error from the child. */
-
- switch (buf[0])
+ case CHILD_NO_ERROR:
+ if (child_pid && dont_wait)
{
- case CHILD_NO_ERROR:
- break;
-
- case CHILD_CHDIR_FAILED:
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_CHDIR,
- _("Failed to change to directory '%s' (%s)"),
- working_directory,
- g_strerror (buf[1]));
- goto cleanup_and_fail;
-
- case CHILD_SPAWN_FAILED:
- g_set_error (error,
- G_SPAWN_ERROR,
- G_SPAWN_ERROR_FAILED,
- _("Failed to execute child process (%s)"),
- g_strerror (buf[1]));
- goto cleanup_and_fail;
+ /* helper is our HANDLE for gspawn-win32-helper. It has
+ * told us the HANDLE of its child. Duplicate that into
+ * a HANDLE valid in this process.
+ */
+ if (!DuplicateHandle ((HANDLE) helper, (HANDLE) buf[1],
+ GetCurrentProcess (), (LPHANDLE) child_pid,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ *child_pid = 0;
}
+ else if (child_pid)
+ *child_pid = 0;
+ break;
+
+ case CHILD_CHDIR_FAILED:
+ g_set_error (error,
+ G_SPAWN_ERROR,
+ G_SPAWN_ERROR_CHDIR,
+ _("Failed to change to directory '%s' (%s)"),
+ working_directory,
+ g_strerror (buf[1]));
+ goto cleanup_and_fail;
+
+ case CHILD_SPAWN_FAILED:
+ g_set_error (error,
+ G_SPAWN_ERROR,
+ G_SPAWN_ERROR_FAILED,
+ _("Failed to execute child process (%s)"),
+ g_strerror (buf[1]));
+ goto cleanup_and_fail;
}
/* Success against all odds! return the information */
if (standard_error)
*standard_error = stderr_pipe[0];
if (exit_status)
- *exit_status = status;
+ *exit_status = buf[1];
return TRUE;
cleanup_and_fail:
+ if (helper != -1)
+ CloseHandle ((HANDLE) helper);
close_and_invalidate (&child_err_report_pipe[0]);
close_and_invalidate (&child_err_report_pipe[1]);
close_and_invalidate (&stdin_pipe[0]);