kernel32: Use double-fork to avoid leaving zombie processes.
This commit is contained in:
parent
7a88d5a1e4
commit
5bac5ee26e
|
@ -41,6 +41,9 @@
|
||||||
# include <sys/prctl.h>
|
# include <sys/prctl.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#ifdef HAVE_SYS_WAIT_H
|
||||||
|
# include <sys/wait.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -1505,11 +1508,11 @@ static int fork_and_exec( const char *filename, const WCHAR *cmdline, const WCHA
|
||||||
|
|
||||||
if (!(pid = fork())) /* child */
|
if (!(pid = fork())) /* child */
|
||||||
{
|
{
|
||||||
close( fd[0] );
|
if (!(pid = fork())) /* grandchild */
|
||||||
|
|
||||||
if (flags & (CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE | DETACHED_PROCESS))
|
|
||||||
{
|
{
|
||||||
if (!(pid = fork()))
|
close( fd[0] );
|
||||||
|
|
||||||
|
if (flags & (CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE | DETACHED_PROCESS))
|
||||||
{
|
{
|
||||||
int nullfd = open( "/dev/null", O_RDWR );
|
int nullfd = open( "/dev/null", O_RDWR );
|
||||||
setsid();
|
setsid();
|
||||||
|
@ -1521,36 +1524,41 @@ static int fork_and_exec( const char *filename, const WCHAR *cmdline, const WCHA
|
||||||
close( nullfd );
|
close( nullfd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pid != -1) _exit(0); /* parent */
|
else
|
||||||
|
{
|
||||||
|
if (stdin_fd != -1)
|
||||||
|
{
|
||||||
|
dup2( stdin_fd, 0 );
|
||||||
|
close( stdin_fd );
|
||||||
|
}
|
||||||
|
if (stdout_fd != -1)
|
||||||
|
{
|
||||||
|
dup2( stdout_fd, 1 );
|
||||||
|
close( stdout_fd );
|
||||||
|
}
|
||||||
|
if (stderr_fd != -1)
|
||||||
|
{
|
||||||
|
dup2( stderr_fd, 2 );
|
||||||
|
close( stderr_fd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset signals that we previously set to SIG_IGN */
|
||||||
|
signal( SIGPIPE, SIG_DFL );
|
||||||
|
|
||||||
|
if (newdir) chdir(newdir);
|
||||||
|
|
||||||
|
if (argv && envp) execve( filename, argv, envp );
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (pid <= 0) /* grandchild if exec failed or child if fork failed */
|
||||||
{
|
{
|
||||||
if (stdin_fd != -1)
|
err = errno;
|
||||||
{
|
write( fd[1], &err, sizeof(err) );
|
||||||
dup2( stdin_fd, 0 );
|
_exit(1);
|
||||||
close( stdin_fd );
|
|
||||||
}
|
|
||||||
if (stdout_fd != -1)
|
|
||||||
{
|
|
||||||
dup2( stdout_fd, 1 );
|
|
||||||
close( stdout_fd );
|
|
||||||
}
|
|
||||||
if (stderr_fd != -1)
|
|
||||||
{
|
|
||||||
dup2( stderr_fd, 2 );
|
|
||||||
close( stderr_fd );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset signals that we previously set to SIG_IGN */
|
_exit(0); /* child if fork succeeded */
|
||||||
signal( SIGPIPE, SIG_DFL );
|
|
||||||
|
|
||||||
if (newdir) chdir(newdir);
|
|
||||||
|
|
||||||
if (argv && envp) execve( filename, argv, envp );
|
|
||||||
err = errno;
|
|
||||||
write( fd[1], &err, sizeof(err) );
|
|
||||||
_exit(1);
|
|
||||||
}
|
}
|
||||||
HeapFree( GetProcessHeap(), 0, argv );
|
HeapFree( GetProcessHeap(), 0, argv );
|
||||||
HeapFree( GetProcessHeap(), 0, envp );
|
HeapFree( GetProcessHeap(), 0, envp );
|
||||||
|
@ -1558,10 +1566,18 @@ static int fork_and_exec( const char *filename, const WCHAR *cmdline, const WCHA
|
||||||
if (stdout_fd != -1) close( stdout_fd );
|
if (stdout_fd != -1) close( stdout_fd );
|
||||||
if (stderr_fd != -1) close( stderr_fd );
|
if (stderr_fd != -1) close( stderr_fd );
|
||||||
close( fd[1] );
|
close( fd[1] );
|
||||||
if ((pid != -1) && (read( fd[0], &err, sizeof(err) ) > 0)) /* exec failed */
|
if (pid != -1)
|
||||||
{
|
{
|
||||||
errno = err;
|
/* reap child */
|
||||||
pid = -1;
|
do {
|
||||||
|
err = waitpid(pid, NULL, 0);
|
||||||
|
} while (err < 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (read( fd[0], &err, sizeof(err) ) > 0) /* exec or second fork failed */
|
||||||
|
{
|
||||||
|
errno = err;
|
||||||
|
pid = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pid == -1) FILE_SetDosError();
|
if (pid == -1) FILE_SetDosError();
|
||||||
close( fd[0] );
|
close( fd[0] );
|
||||||
|
@ -1805,11 +1821,11 @@ static pid_t exec_loader( LPCWSTR cmd_line, unsigned int flags, int socketfd,
|
||||||
|
|
||||||
if (exec_only || !(pid = fork())) /* child */
|
if (exec_only || !(pid = fork())) /* child */
|
||||||
{
|
{
|
||||||
char preloader_reserve[64], socket_env[64];
|
if (exec_only || !(pid = fork())) /* grandchild */
|
||||||
|
|
||||||
if (flags & (CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE | DETACHED_PROCESS))
|
|
||||||
{
|
{
|
||||||
if (!(pid = fork()))
|
char preloader_reserve[64], socket_env[64];
|
||||||
|
|
||||||
|
if (flags & (CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE | DETACHED_PROCESS))
|
||||||
{
|
{
|
||||||
int fd = open( "/dev/null", O_RDWR );
|
int fd = open( "/dev/null", O_RDWR );
|
||||||
setsid();
|
setsid();
|
||||||
|
@ -1821,44 +1837,55 @@ static pid_t exec_loader( LPCWSTR cmd_line, unsigned int flags, int socketfd,
|
||||||
close( fd );
|
close( fd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pid != -1) _exit(0); /* parent */
|
else
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (stdin_fd != -1) dup2( stdin_fd, 0 );
|
|
||||||
if (stdout_fd != -1) dup2( stdout_fd, 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stdin_fd != -1) close( stdin_fd );
|
|
||||||
if (stdout_fd != -1) close( stdout_fd );
|
|
||||||
|
|
||||||
/* Reset signals that we previously set to SIG_IGN */
|
|
||||||
signal( SIGPIPE, SIG_DFL );
|
|
||||||
|
|
||||||
sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd );
|
|
||||||
sprintf( preloader_reserve, "WINEPRELOADRESERVE=%lx-%lx",
|
|
||||||
(unsigned long)binary_info->res_start, (unsigned long)binary_info->res_end );
|
|
||||||
|
|
||||||
putenv( preloader_reserve );
|
|
||||||
putenv( socket_env );
|
|
||||||
if (winedebug) putenv( winedebug );
|
|
||||||
if (wineloader) putenv( wineloader );
|
|
||||||
if (unixdir) chdir(unixdir);
|
|
||||||
|
|
||||||
if (argv)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
wine_exec_wine_binary( loader, argv, getenv("WINELOADER") );
|
if (stdin_fd != -1) dup2( stdin_fd, 0 );
|
||||||
|
if (stdout_fd != -1) dup2( stdout_fd, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stdin_fd != -1) close( stdin_fd );
|
||||||
|
if (stdout_fd != -1) close( stdout_fd );
|
||||||
|
|
||||||
|
/* Reset signals that we previously set to SIG_IGN */
|
||||||
|
signal( SIGPIPE, SIG_DFL );
|
||||||
|
|
||||||
|
sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd );
|
||||||
|
sprintf( preloader_reserve, "WINEPRELOADRESERVE=%lx-%lx",
|
||||||
|
(unsigned long)binary_info->res_start, (unsigned long)binary_info->res_end );
|
||||||
|
|
||||||
|
putenv( preloader_reserve );
|
||||||
|
putenv( socket_env );
|
||||||
|
if (winedebug) putenv( winedebug );
|
||||||
|
if (wineloader) putenv( wineloader );
|
||||||
|
if (unixdir) chdir(unixdir);
|
||||||
|
|
||||||
|
if (argv)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
wine_exec_wine_binary( loader, argv, getenv("WINELOADER") );
|
||||||
|
}
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
while (errno == ENOTSUP && exec_only && terminate_main_thread());
|
while (errno == ENOTSUP && exec_only && terminate_main_thread());
|
||||||
#else
|
#else
|
||||||
while (0);
|
while (0);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
_exit(1);
|
||||||
}
|
}
|
||||||
_exit(1);
|
|
||||||
|
_exit(pid == -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pid != -1)
|
||||||
|
{
|
||||||
|
/* reap child */
|
||||||
|
pid_t wret;
|
||||||
|
do {
|
||||||
|
wret = waitpid(pid, NULL, 0);
|
||||||
|
} while (wret < 0 && errno == EINTR);
|
||||||
|
}
|
||||||
|
|
||||||
HeapFree( GetProcessHeap(), 0, wineloader );
|
HeapFree( GetProcessHeap(), 0, wineloader );
|
||||||
HeapFree( GetProcessHeap(), 0, argv );
|
HeapFree( GetProcessHeap(), 0, argv );
|
||||||
return pid;
|
return pid;
|
||||||
|
|
Loading…
Reference in New Issue