diff options
author | Christopher Faylor <me@cgf.cx> | 2005-09-29 02:56:47 +0400 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2005-09-29 02:56:47 +0400 |
commit | 0730fa07632fa954269ed21cbc2f6025dd35f5cf (patch) | |
tree | 3dc70659917cef414b51daaddd83d6093cdf3d2b /winsup/cygwin | |
parent | 503490bb9fd3b8853342128a7961d9f4b9e15d99 (diff) |
Change name from commune_recv to commune_process throughout. Change name from
commune_send to commune_request throughout.
* pinfo.h (PICOM_EXTRASTR): New flag.
(PICOM_FIFO): Define with new flag.
(_pinfo::hello_pid): Delete.
(_pinfo::tothem): Delete.
(_pinfo::fromthem): Delete.
(_pinfo::commune_process): Rename from commune_recv. Add a siginfo_t argument
to declaration.
(_pinfo::commune_request): Rename from commune_send. Change DWORD to
__uint32_t in declaration.
* pinfo.cc (_pinfo::commune_process): Rename from commune_recv. Add siginfo_t
argument. Use information from argument rather than reading from another pipe.
Synchronize with other process's commune event.
(_pinfo::commune_request): Rename from commune_send. Change DWORD to __uint32
in argument. Fill out information in new siginfo_t element and rely on
extended operation of sig_send rather than trying to deal with synchronization
issues here. Use process handle and read pipe information filled out by
sig_send to gather information from the other process.
* sigproc.cc (sig_send): Take special action if "communing" to ensure
synchronization with the other process and to return information about the
other process to the caller.
(talktome): Accept a siginfo_t and handle arguments. Read additional
information from the signal pipe when _si_commune._si_code has the
PICOM_EXTRASTR flag set.
(wait_sig): Pass the transmitted siginfo_t struct and the pipe handle to
talktome. Close pipe read handle as soon as possible after we detect that
we're exiting.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r-- | winsup/cygwin/ChangeLog | 32 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_fifo.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/signal.h | 15 | ||||
-rw-r--r-- | winsup/cygwin/pinfo.cc | 326 | ||||
-rw-r--r-- | winsup/cygwin/pinfo.h | 20 | ||||
-rw-r--r-- | winsup/cygwin/sigproc.cc | 73 |
6 files changed, 219 insertions, 249 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2667ad1ff..64017900b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,5 +1,37 @@ 2005-09-28 Christopher Faylor <cgf@timesys.com> + Change name from commune_recv to commune_process throughout. + Change name from commune_send to commune_request throughout. + * pinfo.h (PICOM_EXTRASTR): New flag. + (PICOM_FIFO): Define with new flag. + (_pinfo::hello_pid): Delete. + (_pinfo::tothem): Delete. + (_pinfo::fromthem): Delete. + (_pinfo::commune_process): Rename from commune_recv. Add a siginfo_t + argument to declaration. + (_pinfo::commune_request): Rename from commune_send. Change DWORD to + __uint32_t in declaration. + * pinfo.cc (_pinfo::commune_process): Rename from commune_recv. Add + siginfo_t argument. Use information from argument rather than reading + from another pipe. Synchronize with other process's commune event. + (_pinfo::commune_request): Rename from commune_send. Change DWORD to + __uint32 in argument. Fill out information in new siginfo_t element + and rely on extended operation of sig_send rather than trying to deal + with synchronization issues here. Use process handle and read pipe + information filled out by sig_send to gather information from the other + process. + * sigproc.cc (sig_send): Take special action if "communing" to ensure + synchronization with the other process and to return information about + the other process to the caller. + (talktome): Accept a siginfo_t and handle arguments. Read additional + information from the signal pipe when _si_commune._si_code has the + PICOM_EXTRASTR flag set. + (wait_sig): Pass the transmitted siginfo_t struct and the pipe handle + to talktome. Close pipe read handle as soon as possible after we + detect that we're exiting. + +2005-09-28 Christopher Faylor <cgf@timesys.com> + * hookapi.cc (hook_or_detect_cygwin): Correct inverted test for whether to allocate a buffer by always allocating a buffer. diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc index 694a51819..14292671a 100644 --- a/winsup/cygwin/fhandler_fifo.cc +++ b/winsup/cygwin/fhandler_fifo.cc @@ -99,7 +99,7 @@ fhandler_fifo::open_not_mine (int flags) commune_result r; if (p->pid != myself->pid) { - r = p->commune_send (PICOM_FIFO, get_win32_name ()); + r = p->commune_request (PICOM_FIFO, get_win32_name ()); if (r.handles[0] == NULL) continue; // process doesn't own fifo debug_printf ("pid %d, handles[0] %p, handles[1] %p", p->pid, diff --git a/winsup/cygwin/include/cygwin/signal.h b/winsup/cygwin/include/cygwin/signal.h index a73565c74..bd1d33c04 100644 --- a/winsup/cygwin/include/cygwin/signal.h +++ b/winsup/cygwin/include/cygwin/signal.h @@ -42,6 +42,20 @@ typedef struct sigevent } sigevent_t; #pragma pack(push,4) +struct _sigcommune +{ + __uint32_t _si_code; + void *_si_read_handle; + void *_si_write_handle; + void *_si_process_handle; + union + { + int _si_fd; + void *_si_pipe_fhandler; + char *_si_str; + }; +}; + typedef struct { int si_signo; /* signal number */ @@ -53,6 +67,7 @@ typedef struct union { __uint32_t __pad[32]; /* plan for future growth */ + struct _sigcommune _si_commune; /* cygwin ipc */ union { /* timers */ diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 2dd727ba1..5c2e2f8a8 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -380,58 +380,24 @@ _pinfo::alive () extern char **__argv; void -_pinfo::commune_recv () +_pinfo::commune_process (siginfo_t& si) { char path[CYG_MAX_PATH]; DWORD nr; - DWORD code; - HANDLE hp; - HANDLE __fromthem = NULL; - HANDLE __tothem = NULL; + HANDLE& tothem = si._si_commune._si_write_handle; + HANDLE process_sync = + OpenSemaphore (SYNCHRONIZE, false, shared_name (path, "commune", si.si_pid)); + if (process_sync) // FIXME: this test shouldn't be necessary + ProtectHandle (process_sync); - hp = OpenProcess (PROCESS_DUP_HANDLE, false, dwProcessId); - if (!hp) - { - sigproc_printf ("couldn't open handle for pid %d(%u)", pid, dwProcessId); - hello_pid = -1; - return; - } - if (!DuplicateHandle (hp, fromthem, hMainProc, &__fromthem, 0, false, DUPLICATE_SAME_ACCESS)) - { - sigproc_printf ("couldn't duplicate fromthem, %E"); - CloseHandle (hp); - hello_pid = -1; - return; - } - - if (!DuplicateHandle (hp, tothem, hMainProc, &__tothem, 0, false, DUPLICATE_SAME_ACCESS)) - { - sigproc_printf ("couldn't duplicate tothem, %E"); - CloseHandle (__fromthem); - CloseHandle (hp); - hello_pid = -1; - return; - } - - hello_pid = 0; - - if (!ReadFile (__fromthem, &code, sizeof code, &nr, NULL) || nr != sizeof code) - { - CloseHandle (hp); - /* __seterrno ();*/ // this is run from the signal thread, so don't set errno - goto out; - } - - switch (code) + switch (si._si_commune._si_code) { case PICOM_CMDLINE: { unsigned n = 1; - CloseHandle (__fromthem); __fromthem = NULL; extern int __argc_safe; const char *argv[__argc_safe + 1]; - CloseHandle (hp); for (int i = 0; i < __argc_safe; i++) { if (IsBadStringPtr (__argv[i], INT32_MAX)) @@ -441,19 +407,19 @@ _pinfo::commune_recv () n += strlen (argv[i]) + 1; } argv[__argc_safe] = NULL; - if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL)) + if (!WriteFile (tothem, &n, sizeof n, &nr, NULL)) { /*__seterrno ();*/ // this is run from the signal thread, so don't set errno sigproc_printf ("WriteFile sizeof argv failed, %E"); } else for (const char **a = argv; *a; a++) - if (!WriteFile (__tothem, *a, strlen (*a) + 1, &nr, NULL)) + if (!WriteFile (tothem, *a, strlen (*a) + 1, &nr, NULL)) { sigproc_printf ("WriteFile arg %d failed, %E", a - argv); break; } - if (!WriteFile (__tothem, "", 1, &nr, NULL)) + if (!WriteFile (tothem, "", 1, &nr, NULL)) { sigproc_printf ("WriteFile null failed, %E"); break; @@ -462,46 +428,40 @@ _pinfo::commune_recv () } case PICOM_CWD: { - CloseHandle (__fromthem); __fromthem = NULL; - CloseHandle (hp); unsigned int n = strlen (cygheap->cwd.get (path, 1, 1, CYG_MAX_PATH)) + 1; - if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL)) + if (!WriteFile (tothem, &n, sizeof n, &nr, NULL)) sigproc_printf ("WriteFile sizeof cwd failed, %E"); - else if (!WriteFile (__tothem, path, n, &nr, NULL)) + else if (!WriteFile (tothem, path, n, &nr, NULL)) sigproc_printf ("WriteFile cwd failed, %E"); break; } case PICOM_ROOT: { - CloseHandle (__fromthem); __fromthem = NULL; - CloseHandle (hp); - unsigned int n; + unsigned n; if (cygheap->root.exists ()) n = strlen (strcpy (path, cygheap->root.posix_path ())) + 1; else n = strlen (strcpy (path, "/")) + 1; - if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL)) + if (!WriteFile (tothem, &n, sizeof n, &nr, NULL)) sigproc_printf ("WriteFile sizeof root failed, %E"); - else if (!WriteFile (__tothem, path, n, &nr, NULL)) + else if (!WriteFile (tothem, path, n, &nr, NULL)) sigproc_printf ("WriteFile root failed, %E"); break; } case PICOM_FDS: { - CloseHandle (__fromthem); __fromthem = NULL; - CloseHandle (hp); unsigned int n = 0; int fd; cygheap_fdenum cfd; while ((fd = cfd.next ()) >= 0) n += sizeof (int); cfd.rewind (); - if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL)) + if (!WriteFile (tothem, &n, sizeof n, &nr, NULL)) sigproc_printf ("WriteFile sizeof fds failed, %E"); else while ((fd = cfd.next ()) >= 0) - if (!WriteFile (__tothem, &fd, sizeof fd, &nr, NULL)) + if (!WriteFile (tothem, &fd, sizeof fd, &nr, NULL)) { sigproc_printf ("WriteFile fd %d failed, %E", fd); break; @@ -510,16 +470,7 @@ _pinfo::commune_recv () } case PICOM_PIPE_FHANDLER: { - HANDLE hdl; - if (!ReadFile (__fromthem, &hdl, sizeof hdl, &nr, NULL) - || nr != sizeof hdl) - { - sigproc_printf ("ReadFile hdl failed, %E"); - CloseHandle (hp); - goto out; - } - CloseHandle (__fromthem); __fromthem = NULL; - CloseHandle (hp); + HANDLE hdl = si._si_commune._si_pipe_fhandler; unsigned int n = 0; cygheap_fdenum cfd; while (cfd.next () >= 0) @@ -527,59 +478,34 @@ _pinfo::commune_recv () { fhandler_pipe *fh = cfd; n = sizeof *fh; - if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL)) + if (!WriteFile (tothem, &n, sizeof n, &nr, NULL)) sigproc_printf ("WriteFile sizeof hdl failed, %E"); - else if (!WriteFile (__tothem, fh, n, &nr, NULL)) + else if (!WriteFile (tothem, fh, n, &nr, NULL)) sigproc_printf ("WriteFile hdl failed, %E"); + break; } - if (!n && !WriteFile (__tothem, &n, sizeof n, &nr, NULL)) + if (!n && !WriteFile (tothem, &n, sizeof n, &nr, NULL)) sigproc_printf ("WriteFile sizeof hdl failed, %E"); break; } case PICOM_FD: { - int fd; - if (!ReadFile (__fromthem, &fd, sizeof fd, &nr, NULL) - || nr != sizeof fd) - { - sigproc_printf ("ReadFile fd failed, %E"); - CloseHandle (hp); - goto out; - } - CloseHandle (__fromthem); __fromthem = NULL; - CloseHandle (hp); + int fd = si._si_commune._si_fd; unsigned int n = 0; cygheap_fdget cfd (fd); if (cfd < 0) n = strlen (strcpy (path, "")) + 1; else n = strlen (cfd->get_proc_fd_name (path)) + 1; - if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL)) + if (!WriteFile (tothem, &n, sizeof n, &nr, NULL)) sigproc_printf ("WriteFile sizeof fd failed, %E"); - else if (!WriteFile (__tothem, path, n, &nr, NULL)) + else if (!WriteFile (tothem, path, n, &nr, NULL)) sigproc_printf ("WriteFile fd failed, %E"); break; } case PICOM_FIFO: { - unsigned len; - if (!ReadFile (__fromthem, &len, sizeof len, &nr, NULL) - || nr != sizeof len) - { - CloseHandle (hp); - /* __seterrno ();*/ // this is run from the signal thread, so don't set errno - goto out; - } - /* Get null-terminated path */ - if (!ReadFile (__fromthem, path, len, &nr, NULL) - || nr != len) - { - CloseHandle (hp); - /* __seterrno ();*/ // this is run from the signal thread, so don't set errno - goto out; - } - - fhandler_fifo *fh = cygheap->fdtab.find_fifo (path); + fhandler_fifo *fh = cygheap->fdtab.find_fifo (si._si_commune._si_str); HANDLE it[2]; if (fh == NULL) it[0] = it[1] = NULL; @@ -587,46 +513,40 @@ _pinfo::commune_recv () { it[0] = fh->get_handle (); it[1] = fh->get_output_handle (); - for (int i = 0; i < 2; i++) - if (!DuplicateHandle (hMainProc, it[i], hp, &it[i], 0, false, - DUPLICATE_SAME_ACCESS)) - { - it[0] = it[1] = NULL; /* FIXME: possibly left a handle open in child? */ - break; - } - debug_printf ("fifo found %p, %p", it[0], it[1]); - fh->close_one_end (); /* FIXME: not quite right - need more handshaking */ } - CloseHandle (hp); - if (!WriteFile (__tothem, it, sizeof (it), &nr, NULL)) + debug_printf ("fifo %sfound %p, %p", fh ? "" : "not ", it[0], it[1]); + if (!WriteFile (tothem, it, sizeof (it), &nr, NULL)) { /*__seterrno ();*/ // this is run from the signal thread, so don't set errno sigproc_printf ("WriteFile read handle failed, %E"); } - - ReadFile (__fromthem, &nr, sizeof (nr), &nr, NULL); + WaitForSingleObject (process_sync, INFINITE); + process_sync = NULL; + if (fh) + fh->close_one_end (); break; } } - -out: - if (__fromthem) - CloseHandle (__fromthem); - if (__tothem) - CloseHandle (__tothem); + if (process_sync) + { + WaitForSingleObject (process_sync, INFINITE); + ForceCloseHandle (process_sync); + } + CloseHandle (tothem); } -#define PIPEBUFSIZE (4096 * sizeof (DWORD)) - commune_result -_pinfo::commune_send (DWORD code, ...) +_pinfo::commune_request (__uint32_t code, ...) { - HANDLE fromthem = NULL, tome = NULL; - HANDLE fromme = NULL, tothem = NULL; DWORD nr; commune_result res; va_list args; + siginfo_t si = {0}; + HANDLE& hp = si._si_commune._si_process_handle; + HANDLE& fromthem = si._si_commune._si_read_handle; + HANDLE request_sync = NULL; + bool locked = false; va_start (args, code); @@ -638,86 +558,45 @@ _pinfo::commune_send (DWORD code, ...) set_errno (ESRCH); goto err; } - if (!CreatePipe (&fromthem, &tome, &sec_all_nih, PIPEBUFSIZE)) - { - sigproc_printf ("first CreatePipe failed, %E"); - __seterrno (); - goto err; - } - if (!CreatePipe (&fromme, &tothem, &sec_all_nih, PIPEBUFSIZE)) - { - sigproc_printf ("second CreatePipe failed, %E"); - __seterrno (); - goto err; - } - myself.lock (); - myself->tothem = tome; - myself->fromthem = fromme; - myself->hello_pid = pid; - if (!WriteFile (tothem, &code, sizeof code, &nr, NULL) || nr != sizeof code) - { - __seterrno (); - goto err; - } - - if (sig_send (this, __SIGCOMMUNE)) - goto err; - /* FIXME: Need something better than an busy loop here */ - bool isalive; - for (int i = 0; (isalive = alive ()) && (i < 10000); i++) - if (myself->hello_pid <= 0) + si._si_commune._si_code = code; + switch (code) + { + case PICOM_PIPE_FHANDLER: + si._si_commune._si_pipe_fhandler = va_arg (args, HANDLE); break; - else - low_priority_sleep (0); - CloseHandle (tome); - tome = NULL; - CloseHandle (fromme); - fromme = NULL; + case PICOM_FD: + si._si_commune._si_fd = va_arg (args, int); + break; - if (!isalive) - { - set_errno (ESRCH); - goto err; + case PICOM_FIFO: + si._si_commune._si_str = va_arg (args, char *); + break; } - if (myself->hello_pid < 0) - { - set_errno (ENOSYS); - goto err; - } + myself.lock (); + locked = true; + char name_buf[CYG_MAX_PATH]; + request_sync = CreateSemaphore (&sec_none_nih, 0, LONG_MAX, + shared_name (name_buf, "commune", myself->pid)); + if (!request_sync) + goto err; + ProtectHandle (request_sync); + + si.si_signo = __SIGCOMMUNE; + if (sig_send (this, si)) + goto err; size_t n; switch (code) { - case PICOM_PIPE_FHANDLER: - { - HANDLE hdl = va_arg (args, HANDLE); - if (!WriteFile (tothem, &hdl, sizeof hdl, &nr, NULL) - || nr != sizeof hdl) - { - __seterrno (); - goto err; - } - } - goto business_as_usual; - case PICOM_FD: - { - int fd = va_arg (args, int); - if (!WriteFile (tothem, &fd, sizeof fd, &nr, NULL) - || nr != sizeof fd) - { - __seterrno (); - goto err; - } - } - goto business_as_usual; case PICOM_CMDLINE: case PICOM_CWD: case PICOM_ROOT: case PICOM_FDS: - business_as_usual: + case PICOM_FD: + case PICOM_PIPE_FHANDLER: if (!ReadFile (fromthem, &n, sizeof n, &nr, NULL) || nr != sizeof n) { __seterrno (); @@ -741,51 +620,42 @@ _pinfo::commune_send (DWORD code, ...) break; case PICOM_FIFO: { - char *path = va_arg (args, char *); - size_t len = strlen (path) + 1; - if (!WriteFile (tothem, &len, sizeof (len), &nr, NULL) - || nr != sizeof (len)) - { - __seterrno (); - goto err; - } - if (!WriteFile (tothem, path, len, &nr, NULL) || nr != len) - { - __seterrno (); - goto err; - } - DWORD x = ReadFile (fromthem, res.handles, sizeof (res.handles), &nr, NULL); - WriteFile (tothem, &x, sizeof (x), &x, NULL); - if (!x) - goto err; - - if (nr != sizeof (res.handles)) + if (!x || nr != sizeof (res.handles)) { - set_errno (EPIPE); + __seterrno (); goto err; } + for (int i = 0; i < 2; i++) + if (!DuplicateHandle (hp, res.handles[i], hMainProc, &res.handles[i], + 0, false, DUPLICATE_SAME_ACCESS)) + { + if (i) + CloseHandle (res.handles[0]); + res.handles[0] = res.handles[1] = NULL; /* FIXME: possibly left a handle open in child? */ + goto err; + } break; } } - CloseHandle (tothem); - CloseHandle (fromthem); goto out; err: - if (tome) - CloseHandle (tome); - if (fromthem) - CloseHandle (fromthem); - if (tothem) - CloseHandle (tothem); - if (fromme) - CloseHandle (fromme); memset (&res, 0, sizeof (res)); out: - myself->hello_pid = 0; - myself.unlock (); + if (request_sync) + { + LONG res; + ReleaseSemaphore (request_sync, 1, &res); + ForceCloseHandle (request_sync); + } + if (locked) + myself.unlock (); + if (hp) + CloseHandle (hp); + if (fromthem) + CloseHandle (fromthem); return res; } @@ -796,7 +666,7 @@ _pinfo::pipe_fhandler (HANDLE hdl, size_t &n) return NULL; if (pid == myself->pid) return NULL; - commune_result cr = commune_send (PICOM_PIPE_FHANDLER, hdl); + commune_result cr = commune_request (PICOM_PIPE_FHANDLER, hdl); n = cr.n; return (fhandler_pipe *) cr.s; } @@ -809,7 +679,7 @@ _pinfo::fd (int fd, size_t &n) return NULL; if (pid != myself->pid) { - commune_result cr = commune_send (PICOM_FD, fd); + commune_result cr = commune_request (PICOM_FD, fd); s = cr.s; n = cr.n; } @@ -833,7 +703,7 @@ _pinfo::fds (size_t &n) return NULL; if (pid != myself->pid) { - commune_result cr = commune_send (PICOM_FDS); + commune_result cr = commune_request (PICOM_FDS); s = cr.s; n = cr.n; } @@ -861,7 +731,7 @@ _pinfo::root (size_t& n) return NULL; if (pid != myself->pid) { - commune_result cr = commune_send (PICOM_ROOT); + commune_result cr = commune_request (PICOM_ROOT); s = cr.s; n = cr.n; } @@ -884,7 +754,7 @@ _pinfo::cwd (size_t& n) return NULL; if (pid != myself->pid) { - commune_result cr = commune_send (PICOM_CWD); + commune_result cr = commune_request (PICOM_CWD); s = cr.s; n = cr.n; } @@ -905,7 +775,7 @@ _pinfo::cmdline (size_t& n) return NULL; if (pid != myself->pid) { - commune_result cr = commune_send (PICOM_CMDLINE); + commune_result cr = commune_request (PICOM_CMDLINE); s = cr.s; n = cr.n; } diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index 564f6f798..1462e5f6d 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -22,8 +22,9 @@ struct commune_result enum picom { + PICOM_EXTRASTR = 0x80000000, PICOM_CMDLINE = 1, - PICOM_FIFO = 2, + PICOM_FIFO = PICOM_EXTRASTR | 2, PICOM_CWD = 3, PICOM_ROOT = 4, PICOM_FDS = 5, @@ -57,9 +58,8 @@ public: pid_t ppid; /* dwProcessId contains the processid used for sending signals. It - * will be reset in a child process when it is capable of receiving - * signals. - */ + will be reset in a child process when it is capable of receiving + signals. */ DWORD dwProcessId; /* Used to spawn a child for fork(), among other things. */ @@ -87,11 +87,6 @@ public: /* Non-zero if process was stopped by a signal. */ char stopsig; - /* commune */ - pid_t hello_pid; - HANDLE tothem; - HANDLE fromthem; - inline void set_has_pgid_children () { if (pgid == pid) @@ -110,10 +105,10 @@ public: sig_mask = mask; } - void commune_recv (); - commune_result commune_send (DWORD, ...); + void commune_process (siginfo_t&); + commune_result commune_request (__uint32_t, ...); bool alive (); - fhandler_pipe *pipe_fhandler (HANDLE hdl, size_t &); + fhandler_pipe *pipe_fhandler (HANDLE, size_t &); char *fd (int fd, size_t &); char *fds (size_t &); char *root (size_t &); @@ -156,7 +151,6 @@ public: HANDLE hProcess; CRITICAL_SECTION _lock; bool waiter_ready; - /* Handle associated with initial Windows pid which started it all. */ class cygthread *wait_thread; void init (pid_t, DWORD, HANDLE) __attribute__ ((regparm(3))); pinfo () {} diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index e27fccdd9..0799a6ac5 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -526,6 +526,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) bool its_me; HANDLE sendsig; sigpacket pack; + bool communing = si.si_signo == __SIGCOMMUNE; pack.wakeup = NULL; bool wait_for_completion; @@ -598,8 +599,29 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) CloseHandle (hp); goto out; } - CloseHandle (hp); VerifyHandle (sendsig); + if (!communing) + CloseHandle (hp); + else + { + si._si_commune._si_process_handle = hp; + + HANDLE& tome = si._si_commune._si_write_handle; + HANDLE& fromthem = si._si_commune._si_read_handle; + if (!CreatePipe (&fromthem, &tome, &sec_all_nih, 0)) + { + sigproc_printf ("CreatePipe for __SIGCOMMUNE failed, %E"); + __seterrno (); + goto out; + } + if (!DuplicateHandle (hMainProc, tome, hp, &tome, false, 0, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) + { + sigproc_printf ("DuplicateHandle for __SIGCOMMUNE failed, %E"); + __seterrno (); + goto out; + } + } } sigproc_printf ("sendsig %p, pid %d, signal %d, its_me %d", sendsig, p->pid, si.si_signo, its_me); @@ -628,8 +650,25 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) ProtectHandle (pack.wakeup); } + char *leader; + size_t packsize; + if (!communing || !(si._si_commune._si_code & PICOM_EXTRASTR)) + { + leader = (char *) &pack; + packsize = sizeof (pack); + } + else + { + size_t n = strlen (si._si_commune._si_str); + char *p = leader = (char *) alloca (sizeof (pack) + sizeof (n) + n); + memcpy (p, &pack, sizeof (pack)); p += sizeof (pack); + memcpy (p, &n, sizeof (n)); p += sizeof (n); + memcpy (p, si._si_commune._si_str, n); p += n; + packsize = p - leader; + } + DWORD nb; - if (!WriteFile (sendsig, &pack, sizeof (pack), &nb, NULL) || nb != sizeof (pack)) + if (!WriteFile (sendsig, leader, packsize, &nb, NULL) || nb != packsize) { /* Couldn't send to the pipe. This probably means that the process is exiting. */ @@ -687,8 +726,16 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) if (wait_for_completion && si.si_signo != __SIGFLUSHFAST) _my_tls.call_signal_handler (); + goto out; out: + if (communing && rc) + { + if (si._si_commune._si_process_handle) + CloseHandle (si._si_commune._si_process_handle); + if (si._si_commune._si_read_handle) + CloseHandle (si._si_commune._si_read_handle); + } if (pack.wakeup) ForceCloseHandle (pack.wakeup); if (si.si_signo != __SIGPENDING) @@ -921,11 +968,23 @@ stopped_or_terminated (waitq *parent_w, _pinfo *child) } static void -talktome (siginfo_t& si) +talktome (siginfo_t& si, HANDLE readsig) { - pinfo p (si.si_pid, PID_MAP_RW); - if (p) - p->commune_recv (); + pinfo pi (si.si_pid); + if (si._si_commune._si_code & PICOM_EXTRASTR) + { + size_t n; + DWORD nb; + if (!ReadFile (readsig, &n, sizeof (n), &nb, NULL) || nb != sizeof (n)) + return; + // FIXME: Is alloca here? + si._si_commune._si_str = (char *) alloca (n + 1); + if (!ReadFile (readsig, si._si_commune._si_str, n, &nb, NULL) || nb != n) + return; + si._si_commune._si_str[n] = '\0'; + } + if (pi) + pi->commune_process (si); } void @@ -1039,7 +1098,7 @@ wait_sig (VOID *) switch (pack.si.si_signo) { case __SIGCOMMUNE: - talktome (pack.si); + talktome (pack.si, readsig); break; case __SIGSTRACE: strace.hello (); |