aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2004-12-24 18:31:23 +0000
committerChristopher Faylor <me@cgf.cx>2004-12-24 18:31:23 +0000
commite1736c2f135a31a8882199169c2dfc5a99f7ce1b (patch)
treed8aa6f3b12f911e2ed8d2727ea205a8973e47a69 /winsup
parent4697fbcd517791570ecc77c32dd9ebf044c4fa03 (diff)
downloadnewlib-e1736c2f135a31a8882199169c2dfc5a99f7ce1b.zip
newlib-e1736c2f135a31a8882199169c2dfc5a99f7ce1b.tar.gz
newlib-e1736c2f135a31a8882199169c2dfc5a99f7ce1b.tar.bz2
* child_info.h (CURR_CHILD_INFO_MAGIC): Update.
(child_info::parent_wr_proc_pipe): Eliminate. * pinfo.h (_pinfo::alert_parent): Move here from pinfo class. (_pinfo::dup_proc_pipe): New method. (_pinfo::sync_proc_pipe): Ditto. * exceptions.cc (sig_handle_tty_stop): Reflect move of alert_parent. * init.cc (dll_entry): Exit with status one if main process called ExitProcess. * pinfo.cc (set_myself): Remove handling of parent_wr_proc_pipe. (_pinfo::exit): Reflect move of alert_parent. Set procinfo to NULL to flag that we are exiting normally. Always use exitcode when exiting (although this could be a little racy). (pinfo::init): Set default exit to SIGTERM. This will be the exit code reported if process is terminated. (_pinfo::dup_proc_pipe): New function. (pinfo::wait): Duplicate wr_proc_pipe to the right place. Use dup_proc_pipe to move the pipe to the child. (_pinfo::sync_proc_pipe): New function. (_pinfo::alert_parent): Move to _pinfo. Make sure that wr_proc_pipe is ours before using it. * sigproc.cc (child_info::child_info): Remove handling of parent_wr_proc_pipe. * spawn.cc (spawn_guts): Pass our wr_proc_pipe to the child when execing. Ensure that exit code of cygwin process started from windows is correctly set.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog28
-rw-r--r--winsup/cygwin/child_info.h3
-rw-r--r--winsup/cygwin/exceptions.cc4
-rw-r--r--winsup/cygwin/init.cc3
-rw-r--r--winsup/cygwin/pinfo.cc103
-rw-r--r--winsup/cygwin/pinfo.h7
-rw-r--r--winsup/cygwin/sigproc.cc2
-rw-r--r--winsup/cygwin/spawn.cc37
8 files changed, 121 insertions, 66 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index e2251d2..4e341a9 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,31 @@
+2004-12-24 Christopher Faylor <cgf@timesys.com>
+
+ * child_info.h (CURR_CHILD_INFO_MAGIC): Update.
+ (child_info::parent_wr_proc_pipe): Eliminate.
+ * pinfo.h (_pinfo::alert_parent): Move here from pinfo class.
+ (_pinfo::dup_proc_pipe): New method.
+ (_pinfo::sync_proc_pipe): Ditto.
+ * exceptions.cc (sig_handle_tty_stop): Reflect move of alert_parent.
+ * init.cc (dll_entry): Exit with status one if main process called
+ ExitProcess.
+ * pinfo.cc (set_myself): Remove handling of parent_wr_proc_pipe.
+ (_pinfo::exit): Reflect move of alert_parent. Set procinfo to NULL to
+ flag that we are exiting normally. Always use exitcode when exiting
+ (although this could be a little racy).
+ (pinfo::init): Set default exit to SIGTERM. This will be the exit code
+ reported if process is terminated.
+ (_pinfo::dup_proc_pipe): New function.
+ (pinfo::wait): Duplicate wr_proc_pipe to the right place. Use
+ dup_proc_pipe to move the pipe to the child.
+ (_pinfo::sync_proc_pipe): New function.
+ (_pinfo::alert_parent): Move to _pinfo. Make sure that wr_proc_pipe is
+ ours before using it.
+ * sigproc.cc (child_info::child_info): Remove handling of
+ parent_wr_proc_pipe.
+ * spawn.cc (spawn_guts): Pass our wr_proc_pipe to the child when
+ execing. Ensure that exit code of cygwin process started from windows
+ is correctly set.
+
2004-12-23 Pierre Humblet <pierre.humblet@ieee.org>
Christopher Faylor <cgf@timesys.com>
diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h
index 97cf455..33133d6 100644
--- a/winsup/cygwin/child_info.h
+++ b/winsup/cygwin/child_info.h
@@ -29,7 +29,7 @@ enum child_info_types
#define EXEC_MAGIC_SIZE sizeof(child_info)
-#define CURR_CHILD_INFO_MAGIC 0x17ad771aU
+#define CURR_CHILD_INFO_MAGIC 0xd079e02U
/* NOTE: Do not make gratuitous changes to the names or organization of the
below class. The layout is checksummed to determine compatibility between
@@ -49,7 +49,6 @@ public:
void *cygheap_max;
DWORD cygheap_reserve_sz;
HANDLE cygheap_h;
- HANDLE parent_wr_proc_pipe;
unsigned fhandler_union_cb;
child_info (unsigned, child_info_types);
~child_info ();
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index bc28cc8..9993ef4 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -600,7 +600,7 @@ sig_handle_tty_stop (int sig)
}
myself->stopsig = sig;
- myself.alert_parent (sig);
+ myself->alert_parent (sig);
sigproc_printf ("process %d stopped by signal %d", myself->pid, sig);
HANDLE w4[2];
w4[0] = sigCONT;
@@ -610,7 +610,7 @@ sig_handle_tty_stop (int sig)
case WAIT_OBJECT_0:
case WAIT_OBJECT_0 + 1:
reset_signal_arrived ();
- myself.alert_parent (SIGCONT);
+ myself->alert_parent (SIGCONT);
break;
default:
api_fatal ("WaitSingleObject failed, %E");
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
index 7ba0dc3..261b20b 100644
--- a/winsup/cygwin/init.cc
+++ b/winsup/cygwin/init.cc
@@ -13,6 +13,7 @@ details. */
#include "thread.h"
#include "perprocess.h"
#include "cygtls.h"
+#include "pinfo.h"
int NO_COPY dynamically_loaded;
static char *search_for = (char *) cygthread::stub;
@@ -126,6 +127,8 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
dll_crt0_0 ();
break;
case DLL_PROCESS_DETACH:
+ if (myself)
+ myself->exitcode = 1 << 8;
break;
case DLL_THREAD_ATTACH:
munge_threadfunc ();
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index ec51c85..69a4380 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -44,8 +44,6 @@ pinfo NO_COPY myself ((_pinfo *)&pinfo_dummy); // Avoid myself != NULL checks
void __stdcall
set_myself (HANDLE h)
{
- extern child_info *child_proc_info;
-
if (!h)
cygheap->pid = cygwin_pid (GetCurrentProcessId ());
myself.init (cygheap->pid, PID_IN_USE | PID_MYSELF, h);
@@ -68,19 +66,11 @@ set_myself (HANDLE h)
}
else if (!myself->wr_proc_pipe)
myself->start_time = time (NULL); /* Register our starting time. */
- else
+ else if (cygheap->pid_handle)
{
- /* We've inherited the parent's wr_proc_pipe. We don't need it,
- so close it. */
- if (child_proc_info->parent_wr_proc_pipe)
- CloseHandle (child_proc_info->parent_wr_proc_pipe);
- if (cygheap->pid_handle)
- {
- ForceCloseHandle (cygheap->pid_handle);
- cygheap->pid_handle = NULL;
- }
+ ForceCloseHandle (cygheap->pid_handle);
+ cygheap->pid_handle = NULL;
}
-# undef child_proc_info
return;
}
@@ -117,9 +107,9 @@ _pinfo::exit (UINT n, bool norecord)
exit_state = ES_FINAL;
cygthread::terminate ();
if (norecord)
- sigproc_terminate (); /* Just terminate signal and process stuff */
+ sigproc_terminate (); /* Just terminate signal and process stuff */
else
- exitcode = n; /* We're really exiting. Record the UNIX exit code. */
+ exitcode = n; /* We're really exiting. Record the UNIX exit code. */
if (this)
{
@@ -135,7 +125,7 @@ _pinfo::exit (UINT n, bool norecord)
/* We could just let this happen automatically when the process
exits but this should gain us a microsecond or so by notifying
the parent early. */
- myself.alert_parent (0);
+ myself->alert_parent (0);
}
}
@@ -143,7 +133,8 @@ _pinfo::exit (UINT n, bool norecord)
sigproc_printf ("Calling ExitProcess %d", n);
_my_tls.stacklock = 0;
_my_tls.stackptr = _my_tls.stack;
- ExitProcess (n);
+ myself.procinfo = NULL; // This breaks the abstraction a little doesn't it?
+ ExitProcess (exitcode);
}
void
@@ -273,7 +264,10 @@ pinfo::init (pid_t n, DWORD flag, HANDLE in_h)
if (!created)
/* nothing */;
else if (!(flag & PID_EXECED))
- procinfo->pid = n;
+ {
+ procinfo->pid = n;
+ procinfo->exitcode = SIGTERM;
+ }
else
{
procinfo->process_state |= PID_IN_USE | PID_EXECED;
@@ -664,15 +658,10 @@ _pinfo::cmdline (size_t& n)
}
/* This is the workhorse which waits for the write end of the pipe
- created during new process creation. If the pipe is closed, it is
- assumed that the cygwin pid has exited. Otherwise, various "signals"
- can be sent to the parent to inform the parent to perform a certain
- action.
-
- This code was originally written to eliminate the need for "reparenting"
- but, unfortunately, reparenting is still needed in order to get the
- exit code of an execed windows process. Otherwise, the exit code of
- a cygwin process comes from the exitcode field in _pinfo. */
+ created during new process creation. If the pipe is closed or a zero
+ is received on the pipe, it is assumed that the cygwin pid has exited.
+ Otherwise, various "signals" can be sent to the parent to inform the
+ parent to perform a certain action. */
static DWORD WINAPI
proc_waiter (void *arg)
{
@@ -768,29 +757,41 @@ proc_waiter (void *arg)
return 0;
}
+bool
+_pinfo::dup_proc_pipe (HANDLE hProcess)
+{
+ bool res = DuplicateHandle (hMainProc, wr_proc_pipe, hProcess, &wr_proc_pipe,
+ 0, FALSE,
+ DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
+ if (!res)
+ sigproc_printf ("DuplicateHandle failed, pid %d, hProcess %p, %E", pid, hProcess);
+ else
+ {
+ wr_proc_pipe_owner = dwProcessId;
+ sigproc_printf ("closed wr_proc_pipe %p for pid %d(%u)", wr_proc_pipe,
+ pid, dwProcessId);
+ }
+ return res;
+}
+
/* function to set up the process pipe and kick off proc_waiter */
int
pinfo::wait ()
{
- HANDLE out;
/* FIXME: execed processes should be able to wait for pids that were started
by the process which execed them. */
- if (!CreatePipe (&rd_proc_pipe, &out, &sec_none_nih, 16))
+ if (!CreatePipe (&rd_proc_pipe, &((*this)->wr_proc_pipe), &sec_none_nih, 16))
{
system_printf ("Couldn't create pipe tracker for pid %d, %E",
(*this)->pid);
return 0;
}
- /* Duplicate the write end of the pipe into the subprocess. Make it inheritable
- so that all of the execed children get it. */
- if (!DuplicateHandle (hMainProc, out, hProcess, &((*this)->wr_proc_pipe), 0,
- TRUE, DUPLICATE_SAME_ACCESS))
+
+ if (!(*this)->dup_proc_pipe (hProcess))
{
- system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid,
- hProcess);
+ system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid, hProcess);
return 0;
}
- CloseHandle (out); /* Don't need this end in this proces */
preserve (); /* Preserve the shared memory associated with the pinfo */
@@ -808,26 +809,38 @@ pinfo::wait ()
return 1;
}
+void
+_pinfo::sync_proc_pipe ()
+{
+ if (wr_proc_pipe && wr_proc_pipe != INVALID_HANDLE_VALUE)
+ while (wr_proc_pipe_owner != GetCurrentProcessId ())
+ low_priority_sleep (0);
+}
+
/* function to send a "signal" to the parent when something interesting happens
in the child. */
bool
-pinfo::alert_parent (char sig)
+_pinfo::alert_parent (char sig)
{
DWORD nb = 0;
/* Send something to our parent. If the parent has gone away,
close the pipe. */
- if (myself->wr_proc_pipe == INVALID_HANDLE_VALUE
+ if (wr_proc_pipe == INVALID_HANDLE_VALUE
|| !myself->wr_proc_pipe)
/* no parent */;
- else if (WriteFile (myself->wr_proc_pipe, &sig, 1, &nb, NULL))
- /* all is well */;
- else if (GetLastError () != ERROR_BROKEN_PIPE)
- debug_printf ("sending %d notification to parent failed, %E", sig);
else
{
- HANDLE closeit = myself->wr_proc_pipe;
- myself->wr_proc_pipe = INVALID_HANDLE_VALUE;
- CloseHandle (closeit);
+ sync_proc_pipe ();
+ if (WriteFile (wr_proc_pipe, &sig, 1, &nb, NULL))
+ /* all is well */;
+ else if (GetLastError () != ERROR_BROKEN_PIPE)
+ debug_printf ("sending %d notification to parent failed, %E", sig);
+ else
+ {
+ HANDLE closeit = wr_proc_pipe;
+ wr_proc_pipe = INVALID_HANDLE_VALUE;
+ CloseHandle (closeit);
+ }
}
return (bool) nb;
}
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index 6516832..dd998a6 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -106,6 +106,9 @@ public:
bool alive ();
char *cmdline (size_t &);
void set_ctty (class tty_min *, int, class fhandler_tty_slave *);
+ bool dup_proc_pipe (HANDLE) __attribute__ ((regparm(2)));
+ void sync_proc_pipe ();
+ bool alert_parent (char);
friend void __stdcall set_myself (HANDLE);
@@ -117,6 +120,7 @@ private:
sigset_t sig_mask;
public:
HANDLE wr_proc_pipe;
+ DWORD wr_proc_pipe_owner;
friend class pinfo;
};
@@ -163,8 +167,6 @@ public:
operator _pinfo * () const {return procinfo;}
// operator bool () const {return (int) h;}
void preserve () { destroy = false; }
- bool alert_parent (char);
- bool parent_alive () { return alert_parent (__ALERT_ALIVE); }
#ifndef _SIGPROC_H
int remember () {system_printf ("remember is not here"); return 0;}
#else
@@ -178,6 +180,7 @@ public:
#endif
HANDLE shared_handle () {return h;}
void set_acl();
+ friend class _pinfo;
};
#define ISSTATE(p, f) (!!((p)->process_state & f))
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 934988d..b5a2815 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -735,8 +735,6 @@ child_info::child_info (unsigned in_cb, child_info_types chtype)
if (chtype != PROC_SPAWN)
subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
sigproc_printf ("subproc_ready %p", subproc_ready);
- if (chtype != PROC_EXEC && myself->wr_proc_pipe != INVALID_HANDLE_VALUE)
- parent_wr_proc_pipe = myself->wr_proc_pipe;
}
child_info::~child_info ()
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 1c84fad..3fcf92c 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -796,16 +796,28 @@ spawn_guts (const char * prog_arg, const char *const *argv,
sigproc_printf ("new process name %s", myself->progname);
close_all_files ();
/* If wr_proc_pipe doesn't exist then this process was not started by a cygwin
- process. So, we need to wait around until the process we've just "execed"
- dies. Use our own wait facility to wait for our own pid to exit (there
- is some minor special case code in proc_waiter and friends to accommodeate
- this). */
+ process. So, we need to wait around until the process we've just "execed"
+ dies. Use our own wait facility to wait for our own pid to exit (there
+ is some minor special case code in proc_waiter and friends to accommodate
+ this).
+
+ If wr_proc_pipe exists, then it should be duplicated to the child.
+ If the child has exited already, that's ok. The parent will pick up
+ on this fact when we exit. dup_proc_pipe also closes our end of the pipe.
+ Note that wr_proc_pipe may also be == INVALID_HANDLE_VALUE. That will make
+ dup_proc_pipe essentially a no-op. */
if (!myself->wr_proc_pipe)
- {
- myself.remember (true);
- wait_for_myself = true;
- myself->wr_proc_pipe = INVALID_HANDLE_VALUE;
- }
+ {
+ myself.remember (false);
+ wait_for_myself = true;
+ }
+ else
+ {
+ /* Make sure that we own wr_proc_pipe just in case we've been
+ previously execed. */
+ myself->sync_proc_pipe ();
+ (void) myself->dup_proc_pipe (pi.hProcess);
+ }
}
else
{
@@ -849,14 +861,13 @@ ForceCloseHandle (pi.hThread);
sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
-if (wait_for_myself)
- waitpid (myself->pid, &res, 0);
-else
- ciresrv.sync (myself, INFINITE);
+ciresrv.sync (myself, INFINITE);
switch (mode)
{
case _P_OVERLAY:
+ if (wait_for_myself)
+ waitpid (myself->pid, &res, 0);
myself->exit (res, 1);
break;
case _P_WAIT: