summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/sigproc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/sigproc.cc')
-rw-r--r--winsup/cygwin/sigproc.cc73
1 files changed, 66 insertions, 7 deletions
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 ();