New internal function.

2008-02-24  Tor Lillqvist  <tml@novell.com>

	* glib/gutils.c (_glib_get_installation_directory): New internal function.

	* glib/gspawn-win32.c: When spawning the helper process, use an
	explicit full path. (#518292)

	* glib/gspawn-win32.c
	* glib/gspawn-win32-helper.c: Fix race condition when using the
	helper process: When the helper process writes the handle of the
	actual started user process to the parent process, it must be
	duplicated in the parent process with DuplicateHandle() so that it
	is a valid handle in that process. However, if the helper process
	has happened to exit before the DuplicateHandle() call, the
	duplication will fail. Thus we must synchronise the helper
	process's exit. Use another pipe for this.

	Take care not to inherit the writing end of this pipe to the
	helper process. Also, in the helper process, take care not to
	inherit either of the pipes used for communication with the parent
	process to the started user process.


svn path=/trunk/; revision=6575
This commit is contained in:
Tor Lillqvist
2008-02-24 21:15:47 +00:00
committed by Tor Lillqvist
parent 3bd512643d
commit 17640e78d3
4 changed files with 126 additions and 21 deletions

View File

@@ -21,6 +21,8 @@
#include "config.h"
#include <fcntl.h>
#undef G_LOG_DOMAIN
#include "glib.h"
#define GSPAWN_HELPER
@@ -151,7 +153,8 @@ WinMain (struct HINSTANCE__ *hInstance,
char *lpszCmdLine,
int nCmdShow)
{
int child_err_report_fd;
int child_err_report_fd = -1;
int helper_sync_fd = -1;
int i;
int fd;
int mode;
@@ -164,6 +167,7 @@ WinMain (struct HINSTANCE__ *hInstance,
int argc;
wchar_t **wargv, **wenvp;
_startupinfo si = { 0 };
char c;
g_assert (__argc >= ARG_COUNT);
@@ -188,6 +192,14 @@ WinMain (struct HINSTANCE__ *hInstance,
if (__argv[ARG_CHILD_ERR_REPORT][strlen (__argv[ARG_CHILD_ERR_REPORT]) - 1] == '#')
argv_zero_offset++;
/* argv[ARG_HELPER_SYNC] is the file descriptor number we read a
* byte that tells us it is OK to exit. We have to wait until the
* parent allows us to exit, so that the parent has had time to
* duplicate the process handle we sent it. Duplicating a handle
* from another process works only if that other process exists.
*/
helper_sync_fd = atoi (__argv[ARG_HELPER_SYNC]);
/* argv[ARG_STDIN..ARG_STDERR] are the file descriptor numbers that
* should be dup2'd to 0, 1 and 2. '-' if the corresponding fd
* should be left alone, and 'z' if it should be connected to the
@@ -270,9 +282,15 @@ WinMain (struct HINSTANCE__ *hInstance,
*/
if (__argv[ARG_CLOSE_DESCRIPTORS][0] == 'y')
for (i = 3; i < 1000; i++) /* FIXME real limit? */
if (i != child_err_report_fd)
if (i != child_err_report_fd && i != helper_sync_fd)
close (i);
/* We don't want our child to inherit the error report and
* helper sync fds.
*/
child_err_report_fd = dup_noninherited (child_err_report_fd, _O_WRONLY);
helper_sync_fd = dup_noninherited (helper_sync_fd, _O_RDONLY);
/* __argv[ARG_WAIT] is "w" to wait for the program to exit */
if (__argv[ARG_WAIT][0] == 'w')
mode = P_WAIT;
@@ -307,5 +325,8 @@ WinMain (struct HINSTANCE__ *hInstance,
write (child_err_report_fd, &handle, sizeof (handle));
else
write (child_err_report_fd, &zero, sizeof (zero));
read (helper_sync_fd, &c, 1);
return 0;
}