OSDN Git Service

1de363f7d0d4747598149a27c3263da26d88205a
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / pinfo.cc
1 /* pinfo.cc: process table support
2
3    Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
4    2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include "miscfuncs.h"
14 #include <stdlib.h>
15 #include "cygerrno.h"
16 #include "security.h"
17 #include "path.h"
18 #include "fhandler.h"
19 #include "dtable.h"
20 #include "sigproc.h"
21 #include "pinfo.h"
22 #include "perprocess.h"
23 #include "environ.h"
24 #include <assert.h>
25 #include "ntdll.h"
26 #include "shared_info.h"
27 #include "cygheap.h"
28 #include "cygmalloc.h"
29 #include "cygtls.h"
30 #include "tls_pbuf.h"
31 #include "child_info.h"
32
33 class pinfo_basic: public _pinfo
34 {
35 public:
36   pinfo_basic();
37 };
38
39 pinfo_basic::pinfo_basic ()
40 {
41   pid = dwProcessId = GetCurrentProcessId ();
42   GetModuleFileNameW (NULL, progname, sizeof (progname));
43   /* Default uid/gid are needed very early to initialize shared user info. */
44   uid = ILLEGAL_UID;
45   gid = UNKNOWN_GID;
46 }
47
48 pinfo_basic myself_initial NO_COPY;
49
50 pinfo NO_COPY myself (static_cast<_pinfo *> (&myself_initial)); // Avoid myself != NULL checks
51
52 bool is_toplevel_proc;
53
54 /* Setup the pinfo structure for this process.  There may already be a
55    _pinfo for this "pid" if h != NULL. */
56
57 void
58 pinfo::thisproc (HANDLE h)
59 {
60   procinfo = NULL;
61
62   if (!h)
63     cygheap->pid = cygwin_pid (myself_initial.pid);
64
65   init (cygheap->pid, PID_IN_USE, h ?: INVALID_HANDLE_VALUE);
66   procinfo->process_state |= PID_IN_USE;
67   procinfo->dwProcessId = myself_initial.pid;
68   procinfo->sendsig = myself_initial.sendsig;
69   wcscpy (procinfo->progname, myself_initial.progname);
70   debug_printf ("myself dwProcessId %u", procinfo->dwProcessId);
71   if (h)
72     {
73       /* here if execed */
74       static pinfo NO_COPY myself_identity;
75       myself_identity.init (cygwin_pid (procinfo->dwProcessId), PID_EXECED, NULL);
76       procinfo->exec_sendsig = NULL;
77       procinfo->exec_dwProcessId = 0;
78     }
79   else if (!child_proc_info)    /* child_proc_info is only set when this process
80                                    was started by another cygwin process */
81     procinfo->start_time = time (NULL); /* Register our starting time. */
82   else if (::cygheap->pid_handle)
83     {
84       ForceCloseHandle (::cygheap->pid_handle);
85       ::cygheap->pid_handle = NULL;
86     }
87 }
88
89 /* Initialize the process table entry for the current task.
90    This is not called for forked tasks, only execed ones.  */
91 void __stdcall
92 pinfo_init (char **envp, int envc)
93 {
94   if (envp)
95     {
96       environ_init (envp, envc);
97       /* spawn has already set up a pid structure for us so we'll use that */
98       myself->process_state |= PID_CYGPARENT;
99     }
100   else
101     {
102       /* Invent our own pid.  */
103
104       myself.thisproc (NULL);
105       myself->ppid = 1;
106       myself->pgid = myself->sid = myself->pid;
107       myself->ctty = -1;
108       myself->uid = ILLEGAL_UID;
109       myself->gid = UNKNOWN_GID;
110       environ_init (NULL, 0);   /* call after myself has been set up */
111       myself->nice = winprio_to_nice (GetPriorityClass (GetCurrentProcess ()));
112       debug_printf ("Set nice to %d", myself->nice);
113     }
114
115   myself->process_state |= PID_ACTIVE;
116   myself->process_state &= ~(PID_INITIALIZING | PID_EXITED | PID_REAPED);
117   debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
118 }
119
120 static DWORD
121 status_exit (DWORD x)
122 {
123   const char *find_first_notloaded_dll (path_conv &);
124   switch (x)
125     {
126     case STATUS_DLL_NOT_FOUND:
127       {
128         char posix_prog[NT_MAX_PATH];
129         UNICODE_STRING uc;
130         RtlInitUnicodeString(&uc, myself->progname);
131         path_conv pc (&uc, PC_NOWARN);
132         mount_table->conv_to_posix_path (pc.get_win32 (), posix_prog, 1);
133         small_printf ("%s: error while loading shared libraries: %s: cannot open shared object file: No such file or directory\n",
134                       posix_prog, find_first_notloaded_dll (pc));
135         x = 127 << 8;
136       }
137       break;
138     case STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION: /* custom error value */
139       /* We've already printed the error message in pseudo-reloc.c */
140       x = 127 << 8;
141       break;
142     case STATUS_ACCESS_VIOLATION:
143       x = SIGSEGV;
144       break;
145     case STATUS_ILLEGAL_INSTRUCTION:
146       x = SIGILL;
147       break;
148     default:
149       debug_printf ("*** STATUS_%p\n", x);
150       x = 127 << 8;
151     }
152   return EXITCODE_SET | x;
153 }
154
155 # define self (*this)
156 void
157 pinfo::set_exit_code (DWORD x)
158 {
159   if (x >= 0xc0000000UL)
160     self->exitcode = status_exit (x);
161   else
162     self->exitcode = EXITCODE_SET | (sigExeced ?: (x & 0xff) << 8);
163 }
164
165 void
166 pinfo::maybe_set_exit_code_from_windows ()
167 {
168   DWORD x = 0xdeadbeef;
169   DWORD oexitcode = self->exitcode;
170
171   if (hProcess && !(self->exitcode & EXITCODE_SET))
172     {
173       WaitForSingleObject (hProcess, INFINITE); /* just to be safe, in case
174                                                    process hasn't quite exited
175                                                    after closing pipe */
176       GetExitCodeProcess (hProcess, &x);
177       set_exit_code (x);
178     }
179   sigproc_printf ("pid %d, exit value - old %p, windows %p, cygwin %p",
180                   self->pid, oexitcode, x, self->exitcode);
181 }
182
183 void
184 pinfo::exit (DWORD n)
185 {
186   minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
187   sigproc_terminate (ES_FINAL);
188   lock_process until_exit (true);
189   cygthread::terminate ();
190
191   if (n != EXITCODE_NOSET)
192     self->exitcode = EXITCODE_SET | n;/* We're really exiting.  Record the UNIX exit code. */
193   else
194     {
195       exit_state = ES_EXEC_EXIT;
196       maybe_set_exit_code_from_windows ();
197     }
198
199   if (myself->ctty > 0 && !iscons_dev (myself->ctty))
200     {
201       lock_ttys here;
202       tty *t = cygwin_shared->tty[device::minor(myself->ctty)];
203       if (!t->slave_alive ())
204         t->setpgid (0);
205     }
206
207   /* FIXME:  There is a potential race between an execed process and its
208      parent here.  I hated to add a mutex just for that, though.  */
209   struct rusage r;
210   fill_rusage (&r, GetCurrentProcess ());
211   add_rusage (&self->rusage_self, &r);
212   int exitcode = self->exitcode & 0xffff;
213   if (!self->cygstarted)
214     exitcode = ((exitcode & 0xff) << 8) | ((exitcode >> 8) & 0xff);
215   sigproc_printf ("Calling ExitProcess n %p, exitcode %p", n, exitcode);
216   if (!TerminateProcess (GetCurrentProcess (), exitcode))
217     system_printf ("TerminateProcess failed, %E");
218   ExitProcess (exitcode);
219 }
220 # undef self
221
222 inline void
223 pinfo::_pinfo_release ()
224 {
225   if (procinfo)
226     {
227       void *unmap_procinfo = procinfo;
228       procinfo = NULL;
229       UnmapViewOfFile (unmap_procinfo);
230     }
231   HANDLE close_h;
232   if (h)
233     {
234       close_h = h;
235       h = NULL;
236       ForceCloseHandle1 (close_h, pinfo_shared_handle);
237     }
238 }
239
240 void
241 pinfo::init (pid_t n, DWORD flag, HANDLE h0)
242 {
243   shared_locations shloc;
244   h = NULL;
245   if (myself && !(flag & PID_EXECED)
246       && (n == myself->pid || (DWORD) n == myself->dwProcessId))
247     {
248       procinfo = myself;
249       destroy = 0;
250       return;
251     }
252
253   void *mapaddr;
254   int createit = flag & (PID_IN_USE | PID_EXECED);
255   DWORD access = FILE_MAP_READ
256                  | (flag & (PID_IN_USE | PID_EXECED | PID_MAP_RW)
257                     ? FILE_MAP_WRITE : 0);
258   if (!h0 || myself.h)
259     shloc = (flag & (PID_IN_USE | PID_EXECED)) ? SH_JUSTCREATE : SH_JUSTOPEN;
260   else
261     {
262       shloc = SH_MYSELF;
263       if (h0 == INVALID_HANDLE_VALUE)
264         h0 = NULL;
265     }
266
267   procinfo = NULL;
268   PSECURITY_ATTRIBUTES sa_buf = (PSECURITY_ATTRIBUTES) alloca (1024);
269   PSECURITY_ATTRIBUTES sec_attribs = sec_user_nih (sa_buf, cygheap->user.sid(),
270                                                    well_known_world_sid,
271                                                    FILE_MAP_READ);
272
273   for (int i = 0; i < 20; i++)
274     {
275       DWORD mapsize;
276       if (flag & PID_EXECED)
277         mapsize = PINFO_REDIR_SIZE;
278       else
279         mapsize = sizeof (_pinfo);
280
281       procinfo = (_pinfo *) open_shared (L"cygpid", n, h0, mapsize, &shloc,
282                                          sec_attribs, access);
283       if (!h0)
284         {
285           if (createit)
286             __seterrno ();
287           return;
288         }
289
290       if (!procinfo)
291         {
292           if (exit_state)
293             return;
294
295           switch (GetLastError ())
296             {
297             case ERROR_INVALID_HANDLE:
298               api_fatal ("MapViewOfFileEx h0 %p, i %d failed, %E", h0, i);
299             case ERROR_INVALID_ADDRESS:
300               mapaddr = NULL;
301             }
302           debug_printf ("MapViewOfFileEx h0 %p, i %d failed, %E", h0, i);
303           yield ();
304           continue;
305         }
306
307       bool created = shloc != SH_JUSTOPEN;
308
309       if ((procinfo->process_state & PID_INITIALIZING) && (flag & PID_NOREDIR)
310           && cygwin_pid (procinfo->dwProcessId) != procinfo->pid)
311         {
312           set_errno (ESRCH);
313           break;
314         }
315
316       if (procinfo->process_state & PID_EXECED)
317         {
318           assert (i == 0);
319           pid_t realpid = procinfo->pid;
320           debug_printf ("execed process windows pid %d, cygwin pid %d", n, realpid);
321           if (realpid == n)
322             api_fatal ("retrieval of execed process info for pid %d failed due to recursion.", n);
323
324           n = realpid;
325           CloseHandle (h0);
326           h0 = NULL;
327           goto loop;
328         }
329
330       /* In certain pathological cases, it is possible for the shared memory
331          region to exist for a while after a process has exited.  This should
332          only be a brief occurrence, so rather than introduce some kind of
333          locking mechanism, just loop.  */
334       if (!created && createit && (procinfo->process_state & (PID_EXITED | PID_REAPED)))
335         {
336           debug_printf ("looping because pid %d, procinfo->pid %d, "
337                         "procinfo->dwProcessid %u has PID_EXITED|PID_REAPED set",
338                         n, procinfo->pid, procinfo->dwProcessId);
339           goto loop;
340         }
341
342       if (!created)
343         /* nothing */;
344       else if (!(flag & PID_EXECED))
345         procinfo->pid = n;
346       else
347         {
348           procinfo->process_state |= PID_IN_USE | PID_EXECED;
349           procinfo->pid = myself->pid;
350         }
351
352       h = h0;   /* Success! */
353       break;
354
355     loop:
356       _pinfo_release ();
357       if (h0)
358         yield ();
359     }
360
361   if (h)
362     {
363       destroy = 1;
364       ProtectHandle1 (h, pinfo_shared_handle);
365     }
366   else
367     {
368       h = h0;
369       _pinfo_release ();
370     }
371 }
372
373 void
374 pinfo::set_acl()
375 {
376   PACL acl_buf = (PACL) alloca (1024);
377   SECURITY_DESCRIPTOR sd;
378   NTSTATUS status;
379
380   sec_acl (acl_buf, true, true, cygheap->user.sid (),
381            well_known_world_sid, FILE_MAP_READ);
382   RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
383   status = RtlSetDaclSecurityDescriptor (&sd, TRUE, acl_buf, FALSE);
384   if (!NT_SUCCESS (status))
385     debug_printf ("RtlSetDaclSecurityDescriptor %p", status);
386   else if ((status = NtSetSecurityObject (h, DACL_SECURITY_INFORMATION, &sd)))
387     debug_printf ("NtSetSecurityObject %p", status);
388 }
389
390 pinfo::pinfo (HANDLE parent, pinfo_minimal& from, pid_t pid):
391   pinfo_minimal (), destroy (false), procinfo (NULL), waiter_ready (false),
392   wait_thread (NULL)
393 {
394   HANDLE herr;
395   const char *duperr = NULL;
396   if (!DuplicateHandle (parent, herr = from.rd_proc_pipe, GetCurrentProcess (),
397                         &rd_proc_pipe, 0, false, DUPLICATE_SAME_ACCESS))
398     duperr = "couldn't duplicate parent rd_proc_pipe handle %p for forked child %d after exec, %E";
399   else if (!DuplicateHandle (parent, herr = from.hProcess, GetCurrentProcess (),
400                              &hProcess, 0, false, DUPLICATE_SAME_ACCESS))
401     duperr = "couldn't duplicate parent process handle %p for forked child %d after exec, %E";
402   else
403     {
404       h = NULL;
405       DuplicateHandle (parent, from.h, GetCurrentProcess (), &h, 0, false,
406                        DUPLICATE_SAME_ACCESS);
407       init (pid, PID_MAP_RW, h);
408       if (*this)
409         return;
410     }
411
412   if (duperr)
413     debug_printf (duperr, herr, pid);
414
415   /* Returning with procinfo == NULL.  Any open handles will be closed by the
416      destructor. */
417 }
418
419 const char *
420 _pinfo::_ctty (char *buf)
421 {
422   if (ctty <= 0)
423     strcpy (buf, "no ctty");
424   else
425     {
426       device d;
427       d.parse (ctty);
428       __small_sprintf (buf, "ctty %s", d.name);
429     }
430   return buf;
431 }
432
433 bool
434 _pinfo::set_ctty (fhandler_termios *fh, int flags)
435 {
436   tty_min& tc = *fh->tc ();
437   debug_printf ("old %s, ctty device number %p, tc.ntty device number %p flags & O_NOCTTY %p", __ctty (), ctty, tc.ntty, flags & O_NOCTTY);
438   if (fh && &tc && (ctty <= 0 || ctty == tc.ntty) && !(flags & O_NOCTTY))
439     {
440       ctty = tc.ntty;
441       if (cygheap->ctty != fh->archetype)
442         {
443           debug_printf ("cygheap->ctty %p, archetype %p", cygheap->ctty, fh->archetype);
444           if (!cygheap->ctty)
445             syscall_printf ("ctty was NULL");
446           else
447             {
448               syscall_printf ("ctty %p, usecount %d", cygheap->ctty,
449                               cygheap->ctty->archetype_usecount (0));
450               cygheap->ctty->close ();
451             }
452           cygheap->ctty = (fhandler_termios *) fh->archetype;
453           if (cygheap->ctty)
454             {
455               fh->archetype_usecount (1);
456               /* guard ctty fh */
457               cygheap->manage_console_count ("_pinfo::set_ctty", 1);
458               report_tty_counts (cygheap->ctty, "ctty", "");
459             }
460         }
461
462       lock_ttys here;
463       syscall_printf ("attaching %s sid %d, pid %d, pgid %d, tty->pgid %d, tty->sid %d",
464                       __ctty (), sid, pid, pgid, tc.getpgid (), tc.getsid ());
465       if (!cygwin_finished_initializing && !myself->cygstarted
466           && pgid == pid && tc.getpgid () && tc.getsid ())
467         {
468           pgid = tc.getpgid ();
469         }
470
471       /* May actually need to do this:
472
473          if (sid == pid && !tc.getsid () || !procinfo (tc.getsid ())->exists)
474
475          but testing for process existence is expensive so we avoid it until
476          an obvious bug surfaces. */
477       if (sid == pid && !tc.getsid ())
478         tc.setsid (sid);
479       sid = tc.getsid ();
480       /* See above */
481       if (!tc.getpgid () && pgid == pid)
482         tc.setpgid (pgid);
483     }
484   debug_printf ("cygheap->ctty now %p, archetype %p", cygheap->ctty, fh->archetype);
485   return ctty > 0;
486 }
487
488 /* Test to determine if a process really exists and is processing signals.
489  */
490 bool __stdcall
491 _pinfo::exists ()
492 {
493   return this && !(process_state & (PID_EXITED | PID_REAPED));
494 }
495
496 bool
497 _pinfo::alive ()
498 {
499   HANDLE h = OpenProcess (PROCESS_QUERY_INFORMATION, false, dwProcessId);
500   if (h)
501     CloseHandle (h);
502   return !!h;
503 }
504
505 DWORD WINAPI
506 commune_process (void *arg)
507 {
508   siginfo_t& si = *((siginfo_t *) arg);
509   tmp_pathbuf tp;
510   char *path = tp.c_get ();
511   DWORD nr;
512   HANDLE& tothem = si._si_commune._si_write_handle;
513   HANDLE process_sync =
514     OpenSemaphore (SYNCHRONIZE, false, shared_name (path, "commune", si.si_pid));
515   if (process_sync)             // FIXME: this test shouldn't be necessary
516     ProtectHandle (process_sync);
517
518   lock_process now ();
519   if (si._si_commune._si_code & PICOM_EXTRASTR)
520     si._si_commune._si_str = (char *) (&si + 1);
521
522   switch (si._si_commune._si_code)
523     {
524     case PICOM_CMDLINE:
525       {
526         sigproc_printf ("processing PICOM_CMDLINE");
527         unsigned n = 0;
528         const char *argv[__argc_safe + 1];
529
530         for (int i = 0; i < __argc_safe; i++)
531           {
532             if (IsBadStringPtr (__argv[i], INT32_MAX))
533               argv[i] = "";
534             else
535               argv[i] = __argv[i];
536             n += strlen (argv[i]) + 1;
537           }
538         argv[__argc_safe] = NULL;
539         if (!WritePipeOverlapped (tothem, &n, sizeof n, &nr, 1000L))
540           {
541             /*__seterrno ();*/  // this is run from the signal thread, so don't set errno
542             sigproc_printf ("WritePipeOverlapped sizeof argv failed, %E");
543           }
544         else
545           for (const char **a = argv; *a; a++)
546             if (!WritePipeOverlapped (tothem, *a, strlen (*a) + 1, &nr, 1000L))
547               {
548                 sigproc_printf ("WritePipeOverlapped arg %d failed, %E",
549                                 a - argv);
550                 break;
551               }
552         break;
553       }
554     case PICOM_CWD:
555       {
556         sigproc_printf ("processing PICOM_CWD");
557         unsigned int n = strlen (cygheap->cwd.get (path, 1, 1, NT_MAX_PATH)) + 1;
558         if (!WritePipeOverlapped (tothem, &n, sizeof n, &nr, 1000L))
559           sigproc_printf ("WritePipeOverlapped sizeof cwd failed, %E");
560         else if (!WritePipeOverlapped (tothem, path, n, &nr, 1000L))
561           sigproc_printf ("WritePipeOverlapped cwd failed, %E");
562         break;
563       }
564     case PICOM_ROOT:
565       {
566         sigproc_printf ("processing PICOM_ROOT");
567         unsigned n;
568         if (cygheap->root.exists ())
569           n = strlen (strcpy (path, cygheap->root.posix_path ())) + 1;
570         else
571           n = strlen (strcpy (path, "/")) + 1;
572         if (!WritePipeOverlapped (tothem, &n, sizeof n, &nr, 1000L))
573           sigproc_printf ("WritePipeOverlapped sizeof root failed, %E");
574         else if (!WritePipeOverlapped (tothem, path, n, &nr, 1000L))
575           sigproc_printf ("WritePipeOverlapped root failed, %E");
576         break;
577       }
578     case PICOM_FDS:
579       {
580         sigproc_printf ("processing PICOM_FDS");
581         unsigned int n = 0;
582         int fd;
583         cygheap_fdenum cfd;
584         while ((fd = cfd.next ()) >= 0)
585           n += sizeof (int);
586         cfd.rewind ();
587         if (!WritePipeOverlapped (tothem, &n, sizeof n, &nr, 1000L))
588           sigproc_printf ("WritePipeOverlapped sizeof fds failed, %E");
589         else
590           while ((fd = cfd.next ()) >= 0)
591             if (!WritePipeOverlapped (tothem, &fd, sizeof fd, &nr, 1000L))
592               {
593                 sigproc_printf ("WritePipeOverlapped fd %d failed, %E", fd);
594                 break;
595               }
596         break;
597       }
598     case PICOM_PIPE_FHANDLER:
599       {
600         sigproc_printf ("processing PICOM_FDS");
601         HANDLE hdl = si._si_commune._si_pipe_fhandler;
602         unsigned int n = 0;
603         cygheap_fdenum cfd;
604         while (cfd.next () >= 0)
605           if (cfd->get_handle () == hdl)
606             {
607               fhandler_pipe *fh = cfd;
608               n = sizeof *fh;
609               if (!WritePipeOverlapped (tothem, &n, sizeof n, &nr, 1000L))
610                 sigproc_printf ("WritePipeOverlapped sizeof hdl failed, %E");
611               else if (!WritePipeOverlapped (tothem, fh, n, &nr, 1000L))
612                 sigproc_printf ("WritePipeOverlapped hdl failed, %E");
613               break;
614             }
615         if (!n && !WritePipeOverlapped (tothem, &n, sizeof n, &nr, 1000L))
616           sigproc_printf ("WritePipeOverlapped sizeof hdl failed, %E");
617         break;
618       }
619     case PICOM_FD:
620       {
621         sigproc_printf ("processing PICOM_FD");
622         int fd = si._si_commune._si_fd;
623         unsigned int n = 0;
624         cygheap_fdget cfd (fd);
625         if (cfd < 0)
626           n = strlen (strcpy (path, "")) + 1;
627         else
628           n = strlen (cfd->get_proc_fd_name (path)) + 1;
629         if (!WritePipeOverlapped (tothem, &n, sizeof n, &nr, 1000L))
630           sigproc_printf ("WritePipeOverlapped sizeof fd failed, %E");
631         else if (!WritePipeOverlapped (tothem, path, n, &nr, 1000L))
632           sigproc_printf ("WritePipeOverlapped fd failed, %E");
633         break;
634       }
635     }
636   if (process_sync)
637     {
638       DWORD res = WaitForSingleObject (process_sync, 5000);
639       if (res != WAIT_OBJECT_0)
640         sigproc_printf ("WFSO failed - %d, %E", res);
641       else
642         sigproc_printf ("synchronized with pid %d", si.si_pid);
643       ForceCloseHandle (process_sync);
644     }
645   CloseHandle (tothem);
646   _my_tls._ctinfo->auto_release ();
647   return 0;
648 }
649
650 commune_result
651 _pinfo::commune_request (__uint32_t code, ...)
652 {
653   DWORD nr;
654   commune_result res;
655   va_list args;
656   siginfo_t si = {0};
657   HANDLE& hp = si._si_commune._si_process_handle;
658   HANDLE& fromthem = si._si_commune._si_read_handle;
659   HANDLE request_sync = NULL;
660   bool locked = false;
661
662   res.s = NULL;
663   res.n = 0;
664
665   if (!this || !pid)
666     {
667       set_errno (ESRCH);
668       goto err;
669     }
670
671   va_start (args, code);
672   si._si_commune._si_code = code;
673   switch (code)
674     {
675     case PICOM_PIPE_FHANDLER:
676       si._si_commune._si_pipe_fhandler = va_arg (args, HANDLE);
677       break;
678
679     case PICOM_FD:
680       si._si_commune._si_fd = va_arg (args, int);
681       break;
682
683     break;
684     }
685   va_end (args);
686
687   locked = true;
688   char name_buf[MAX_PATH];
689   request_sync = CreateSemaphore (&sec_none_nih, 0, LONG_MAX,
690                                   shared_name (name_buf, "commune", myself->pid));
691   if (!request_sync)
692     goto err;
693   ProtectHandle (request_sync);
694
695   si.si_signo = __SIGCOMMUNE;
696   if (sig_send (this, si))
697     {
698       ForceCloseHandle (request_sync);  /* don't signal semaphore since there was apparently no receiving process */
699       request_sync = NULL;
700       goto err;
701     }
702
703   size_t n;
704   switch (code)
705     {
706     case PICOM_CMDLINE:
707     case PICOM_CWD:
708     case PICOM_ROOT:
709     case PICOM_FDS:
710     case PICOM_FD:
711     case PICOM_PIPE_FHANDLER:
712       if (!ReadPipeOverlapped (fromthem, &n, sizeof n, &nr, 500L)
713           || nr != sizeof n)
714         {
715           __seterrno ();
716           goto err;
717         }
718       if (!n)
719         res.s = NULL;
720       else
721         {
722           res.s = (char *) cmalloc_abort (HEAP_COMMUNE, n);
723           char *p;
724           for (p = res.s;
725                n && ReadPipeOverlapped (fromthem, p, n, &nr, 500L);
726                p += nr, n -= nr)
727             continue;
728           if (n)
729             {
730               __seterrno ();
731               goto err;
732             }
733           res.n = p - res.s;
734         }
735       break;
736     }
737   goto out;
738
739 err:
740   memset (&res, 0, sizeof (res));
741
742 out:
743   if (request_sync)
744     {
745       LONG res;
746       ReleaseSemaphore (request_sync, 1, &res);
747       ForceCloseHandle (request_sync);
748     }
749   if (hp)
750     CloseHandle (hp);
751   if (fromthem)
752     CloseHandle (fromthem);
753   return res;
754 }
755
756 fhandler_pipe *
757 _pinfo::pipe_fhandler (HANDLE hdl, size_t &n)
758 {
759   if (!this || !pid)
760     return NULL;
761   if (pid == myself->pid)
762     return NULL;
763   commune_result cr = commune_request (PICOM_PIPE_FHANDLER, hdl);
764   n = cr.n;
765   return (fhandler_pipe *) cr.s;
766 }
767
768 char *
769 _pinfo::fd (int fd, size_t &n)
770 {
771   char *s;
772   if (!this || !pid)
773     return NULL;
774   if (pid != myself->pid)
775     {
776       commune_result cr = commune_request (PICOM_FD, fd);
777       s = cr.s;
778       n = cr.n;
779     }
780   else
781     {
782       cygheap_fdget cfd (fd);
783       if (cfd < 0)
784         s = cstrdup ("");
785       else
786         s = cfd->get_proc_fd_name ((char *) cmalloc_abort (HEAP_COMMUNE, NT_MAX_PATH));
787       n = strlen (s) + 1;
788     }
789   return s;
790 }
791
792 char *
793 _pinfo::fds (size_t &n)
794 {
795   char *s;
796   if (!this || !pid)
797     return NULL;
798   if (pid != myself->pid)
799     {
800       commune_result cr = commune_request (PICOM_FDS);
801       s = cr.s;
802       n = cr.n;
803     }
804   else
805     {
806       n = 0;
807       int fd;
808       cygheap_fdenum cfd (true);
809       while ((fd = cfd.next ()) >= 0)
810         n += sizeof (int);
811       cfd.rewind ();
812       s = (char *) cmalloc_abort (HEAP_COMMUNE, n);
813       int *p = (int *) s;
814       while ((fd = cfd.next ()) >= 0 && (char *) p - s < (int) n)
815         *p++ = fd;
816     }
817   return s;
818 }
819
820 char *
821 _pinfo::root (size_t& n)
822 {
823   char *s;
824   if (!this || !pid)
825     return NULL;
826   if (pid != myself->pid)
827     {
828       commune_result cr = commune_request (PICOM_ROOT);
829       s = cr.s;
830       n = cr.n;
831     }
832   else
833     {
834       if (cygheap->root.exists ())
835         s = cstrdup (cygheap->root.posix_path ());
836       else
837         s = cstrdup ("/");
838       n = strlen (s) + 1;
839     }
840   return s;
841 }
842
843 char *
844 _pinfo::cwd (size_t& n)
845 {
846   char *s;
847   if (!this || !pid)
848     return NULL;
849   if (pid != myself->pid)
850     {
851       commune_result cr = commune_request (PICOM_CWD);
852       s = cr.s;
853       n = cr.n;
854     }
855   else
856     {
857       s = (char *) cmalloc_abort (HEAP_COMMUNE, NT_MAX_PATH);
858       cygheap->cwd.get (s, 1, 1, NT_MAX_PATH);
859       n = strlen (s) + 1;
860     }
861   return s;
862 }
863
864 char *
865 _pinfo::cmdline (size_t& n)
866 {
867   char *s;
868   if (!this || !pid)
869     return NULL;
870   if (pid != myself->pid)
871     {
872       commune_result cr = commune_request (PICOM_CMDLINE);
873       s = cr.s;
874       n = cr.n;
875     }
876   else
877     {
878       n = 0;
879       for (char **a = __argv; *a; a++)
880         n += strlen (*a) + 1;
881       char *p;
882       p = s = (char *) cmalloc_abort (HEAP_COMMUNE, n);
883       for (char **a = __argv; *a; a++)
884         {
885           strcpy (p, *a);
886           p = strchr (p, '\0') + 1;
887         }
888     }
889   return s;
890 }
891
892 /* This is the workhorse which waits for the write end of the pipe
893    created during new process creation.  If the pipe is closed or a zero
894    is received on the pipe, it is assumed that the cygwin pid has exited.
895    Otherwise, various "signals" can be sent to the parent to inform the
896    parent to perform a certain action. */
897 static DWORD WINAPI
898 proc_waiter (void *arg)
899 {
900   pinfo vchild = *(pinfo *) arg;
901   ((pinfo *) arg)->waiter_ready = true;
902
903   siginfo_t si = {0};
904   si.si_signo = SIGCHLD;
905   si.si_code = CLD_EXITED;
906   si.si_pid = vchild->pid;
907 #if 0   // FIXME: This is tricky to get right
908   si.si_utime = pchildren[rc]->rusage_self.ru_utime;
909   si.si_stime = pchildren[rc].rusage_self.ru_stime;
910 #endif
911   pid_t pid = vchild->pid;
912   bool its_me = vchild == myself;
913
914   for (;;)
915     {
916       DWORD nb;
917       char buf = '\0';
918
919       if (!ReadFile (vchild.rd_proc_pipe, &buf, 1, &nb, NULL)
920           && GetLastError () != ERROR_BROKEN_PIPE)
921         {
922           system_printf ("error on read of child wait pipe %p, %E", vchild.rd_proc_pipe);
923           break;
924         }
925
926       if (!its_me && have_execed_cygwin)
927         break;
928
929       si.si_uid = vchild->uid;
930
931       switch (buf)
932         {
933         case __ALERT_ALIVE:
934           continue;
935         case 0:
936           /* Child exited.  Do some cleanup and signal myself.  */
937           vchild.maybe_set_exit_code_from_windows ();
938           if (WIFEXITED (vchild->exitcode))
939             si.si_code = CLD_EXITED;
940           else if (WCOREDUMP (vchild->exitcode))
941             si.si_code = CLD_DUMPED;
942           else
943             si.si_code = CLD_KILLED;
944           si.si_status = vchild->exitcode;
945           vchild->process_state = PID_EXITED;
946           /* This should always be last.  Do not use vchild-> beyond this point */
947           break;
948         case SIGTTIN:
949         case SIGTTOU:
950         case SIGTSTP:
951         case SIGSTOP:
952           if (ISSTATE (myself, PID_NOCLDSTOP))  // FIXME: No need for this flag to be in _pinfo any longer
953             continue;
954           /* Child stopped.  Signal myself.  */
955           si.si_code = CLD_STOPPED;
956           break;
957         case SIGCONT:
958           continue;
959         default:
960           system_printf ("unknown value %d on proc pipe", buf);
961           continue;
962         }
963
964       if (its_me && ch_spawn.signal_myself_exited ())
965         break;
966
967       /* Send a SIGCHLD to myself.   We do this here, rather than in proc_subproc
968          to avoid the proc_subproc lock since the signal thread will eventually
969          be calling proc_subproc and could unnecessarily block. */
970       sig_send (myself_nowait, si);
971
972       /* If we're just stopped or got a continue signal, keep looping.
973          Otherwise, return this thread to the pool. */
974       if (buf != '\0')
975         sigproc_printf ("looping");
976       else
977         break;
978     }
979
980   sigproc_printf ("exiting wait thread for pid %d", pid);
981   vchild.wait_thread = NULL;
982   _my_tls._ctinfo->auto_release ();     /* automatically return the cygthread to the cygthread pool */
983   return 0;
984 }
985
986 #ifdef DEBUGGING
987 #define warn_printf api_fatal
988 #else
989 #define warn_printf system_printf
990 #endif
991 HANDLE
992 _pinfo::dup_proc_pipe (HANDLE hProcess)
993 {
994   DWORD flags = DUPLICATE_SAME_ACCESS;
995   HANDLE orig_wr_proc_pipe = wr_proc_pipe;
996   /* Can't set DUPLICATE_CLOSE_SOURCE for exec case because we could be
997      execing a non-cygwin process and we need to set the exit value before the
998      parent sees it.  */
999   if (this != myself || is_toplevel_proc)
1000     flags |= DUPLICATE_CLOSE_SOURCE;
1001   bool res = DuplicateHandle (GetCurrentProcess (), wr_proc_pipe,
1002                               hProcess, &wr_proc_pipe, 0, FALSE, flags);
1003   if (!res && WaitForSingleObject (hProcess, 0) != WAIT_OBJECT_0)
1004     {
1005       wr_proc_pipe = orig_wr_proc_pipe;
1006       warn_printf ("something failed for pid %d: res %d, hProcess %p, wr_proc_pipe %p vs. %p, %E",
1007                    res, pid, hProcess, wr_proc_pipe, orig_wr_proc_pipe);
1008     }
1009   else
1010     {
1011       wr_proc_pipe_owner = dwProcessId;
1012       sigproc_printf ("duped wr_proc_pipe %p for pid %d(%u)", wr_proc_pipe,
1013                       pid, dwProcessId);
1014     }
1015   return orig_wr_proc_pipe;
1016 }
1017
1018 /* function to set up the process pipe and kick off proc_waiter */
1019 bool
1020 pinfo::wait ()
1021 {
1022   /* If rd_proc_pipe != NULL we're in an execed process which already has
1023      grabbed the read end of the pipe from the previous cygwin process running
1024      with this pid.  */
1025   if (!rd_proc_pipe)
1026     {
1027       /* FIXME: execed processes should be able to wait for pids that were started
1028          by the process which execed them. */
1029       if (!CreatePipe (&rd_proc_pipe, &((*this)->wr_proc_pipe), &sec_none_nih, 16))
1030         {
1031           system_printf ("Couldn't create pipe tracker for pid %d, %E",
1032                          (*this)->pid);
1033           return false;
1034         }
1035
1036       if (!(*this)->dup_proc_pipe (hProcess))
1037         {
1038           system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid, hProcess);
1039           return false;
1040         }
1041     }
1042
1043   preserve ();          /* Preserve the shared memory associated with the pinfo */
1044
1045   waiter_ready = false;
1046   /* Fire up a new thread to track the subprocess */
1047   cygthread *h = new cygthread (proc_waiter, this, "waitproc");
1048   if (!h)
1049     sigproc_printf ("tracking thread creation failed for pid %d", (*this)->pid);
1050   else
1051     {
1052       wait_thread = h;
1053       sigproc_printf ("created tracking thread for pid %d, winpid %p, rd_proc_pipe %p",
1054                       (*this)->pid, (*this)->dwProcessId, rd_proc_pipe);
1055     }
1056
1057   return true;
1058 }
1059
1060 void
1061 _pinfo::sync_proc_pipe ()
1062 {
1063   if (wr_proc_pipe && wr_proc_pipe != INVALID_HANDLE_VALUE)
1064     while (wr_proc_pipe_owner != GetCurrentProcessId ())
1065       yield ();
1066 }
1067
1068 /* function to send a "signal" to the parent when something interesting happens
1069    in the child. */
1070 bool
1071 _pinfo::alert_parent (char sig)
1072 {
1073   DWORD nb = 0;
1074
1075   /* Send something to our parent.  If the parent has gone away, close the pipe.
1076      Don't send if this is an exec stub.
1077
1078      FIXME: Is there a race here if we run this while another thread is attempting
1079      to exec()? */
1080   if (wr_proc_pipe == INVALID_HANDLE_VALUE || !myself->wr_proc_pipe || have_execed)
1081     /* no parent */;
1082   else
1083     {
1084       sync_proc_pipe ();
1085       if (WriteFile (wr_proc_pipe, &sig, 1, &nb, NULL))
1086         /* all is well */;
1087       else if (GetLastError () != ERROR_BROKEN_PIPE)
1088         debug_printf ("sending %d notification to parent failed, %E", sig);
1089       else
1090         {
1091           ppid = 1;
1092           HANDLE closeit = wr_proc_pipe;
1093           wr_proc_pipe = INVALID_HANDLE_VALUE;
1094           CloseHandle (closeit);
1095         }
1096     }
1097   return (bool) nb;
1098 }
1099
1100 void
1101 pinfo::release ()
1102 {
1103   _pinfo_release ();
1104   HANDLE close_h;
1105   if (rd_proc_pipe)
1106     {
1107       close_h = rd_proc_pipe;
1108       rd_proc_pipe = NULL;
1109       ForceCloseHandle1 (close_h, rd_proc_pipe);
1110     }
1111   if (hProcess)
1112     {
1113       close_h = hProcess;
1114       hProcess = NULL;
1115       ForceCloseHandle1 (close_h, childhProc);
1116     }
1117 }
1118
1119 /* DOCTOOL-START
1120
1121 <sect1 id="func-cygwin-winpid-to-pid">
1122   <title>cygwin_winpid_to_pid</title>
1123
1124   <funcsynopsis><funcprototype>
1125     <funcdef>extern "C" pid_t
1126       <function>cygwin_winpid_to_pid</function>
1127       </funcdef>
1128       <paramdef>int <parameter>winpid</parameter></paramdef>
1129   </funcprototype></funcsynopsis>
1130
1131   <para>Given a windows pid, converts to the corresponding Cygwin
1132 pid, if any.  Returns -1 if windows pid does not correspond to
1133 a cygwin pid.</para>
1134   <example>
1135     <title>Example use of cygwin_winpid_to_pid</title>
1136     <programlisting>
1137       extern "C" cygwin_winpid_to_pid (int winpid);
1138       pid_t mypid;
1139       mypid = cygwin_winpid_to_pid (windows_pid);
1140     </programlisting>
1141   </example>
1142 </sect1>
1143
1144    DOCTOOL-END */
1145
1146 extern "C" pid_t
1147 cygwin_winpid_to_pid (int winpid)
1148 {
1149   pinfo p (cygwin_pid (winpid));
1150   if (p)
1151     return p->pid;
1152
1153   set_errno (ESRCH);
1154   return (pid_t) -1;
1155 }
1156
1157
1158 #define slop_pidlist 200
1159 #define size_pidlist(i) (sizeof (pidlist[0]) * ((i) + 1))
1160 #define size_pinfolist(i) (sizeof (pinfolist[0]) * ((i) + 1))
1161 class _onreturn
1162 {
1163   HANDLE *h;
1164 public:
1165   ~_onreturn ()
1166   {
1167     if (h && *h)
1168       {
1169         CloseHandle (*h);
1170         *h = NULL;
1171         h = NULL;
1172       }
1173   }
1174   void no_close_p_handle () {h = NULL;}
1175   _onreturn (HANDLE& _h): h (&_h) {}
1176 };
1177
1178 inline void
1179 winpids::add (DWORD& nelem, bool winpid, DWORD pid)
1180 {
1181   pid_t cygpid = cygwin_pid (pid);
1182
1183   if (nelem >= npidlist)
1184     {
1185       npidlist += slop_pidlist;
1186       pidlist = (DWORD *) realloc (pidlist, size_pidlist (npidlist + 1));
1187       pinfolist = (pinfo *) realloc (pinfolist, size_pinfolist (npidlist + 1));
1188     }
1189
1190   pinfo& p = pinfolist[nelem];
1191   memset (&p, 0, sizeof (p));
1192
1193   /* Open a process to prevent a subsequent exit from invalidating the
1194      shared memory region. */
1195   p.hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, false, pid);
1196   _onreturn onreturn (p.hProcess);
1197
1198   /* If we couldn't open the process then we don't have rights to it and should
1199      make a copy of the shared memory area if it exists (it may not).  */
1200   bool perform_copy;
1201   if (!p.hProcess)
1202     perform_copy = true;
1203   else
1204     perform_copy = make_copy;
1205
1206   p.init (cygpid, PID_NOREDIR | pinfo_access, NULL);
1207
1208   /* If we're just looking for winpids then don't do any special cygwin "stuff* */
1209   if (winpid)
1210     goto out;
1211
1212   /* !p means that we couldn't find shared memory for this pid.  Probably means
1213      that it isn't a cygwin process. */
1214   if (!p)
1215     {
1216       if (!pinfo_access)
1217         return;
1218       p.init (cygpid, PID_NOREDIR, NULL);
1219       if (!p)
1220         return;
1221       }
1222
1223   /* Scan list of previously recorded pids to make sure that this pid hasn't
1224      shown up before.  This can happen when a process execs. */
1225   for (unsigned i = 0; i < nelem; i++)
1226     if (pinfolist[i]->pid == p->pid)
1227       {
1228         if ((_pinfo *) p != (_pinfo *) myself)
1229           p.release ();
1230         return;
1231       }
1232
1233 out:
1234   /* Exit here.
1235
1236      If p is "false" then, eventually any opened process handle will be closed and
1237      the function will exit without adding anything to the pid list.
1238
1239      If p is "true" then we've discovered a cygwin process.
1240
1241      Handle "myself" differently.  Don't copy it and close/zero the handle we
1242      just opened to it.
1243      If not performing a copy, then keep the process handle open for the duration
1244      of the life of the procinfo region to potential races when a new process uses
1245      this pid.
1246      Otherwise, malloc some memory for a copy of the shared memory.
1247
1248      If the malloc failed, then "oh well".  Just keep the shared memory around
1249      and eventually close the handle when the winpids goes out of scope.
1250
1251      If malloc succeeds, copy the procinfo we just grabbed into the new region,
1252      release the shared memory and allow the handle to be closed when this
1253      function returns.
1254
1255      Oh, and add the pid to the list and bump the number of elements.  */
1256
1257   if (p)
1258     {
1259       if (p == (_pinfo *) myself)
1260         /* handle specially.  Close the handle but (eventually) don't
1261            deallocate procinfo in release call */;
1262       else if (!perform_copy)
1263         onreturn.no_close_p_handle ();  /* Don't close the handle until release */
1264       else
1265         {
1266           _pinfo *pnew = (_pinfo *) malloc (sizeof (*p.procinfo));
1267           if (!pnew)
1268             onreturn.no_close_p_handle ();
1269           else
1270             {
1271               *pnew = *p.procinfo;
1272               p.release ();
1273               p.procinfo = pnew;
1274               p.destroy = false;
1275             }
1276         }
1277     }
1278   if (p || winpid)
1279     pidlist[nelem++] = !p ? pid : p->dwProcessId;
1280 }
1281
1282 DWORD
1283 winpids::enum_processes (bool winpid)
1284 {
1285   DWORD nelem = 0;
1286   DWORD cygwin_pid_nelem = 0;
1287   NTSTATUS status;
1288   ULONG context;
1289   struct fdbi
1290     {
1291       DIRECTORY_BASIC_INFORMATION dbi;
1292       WCHAR buf[2][NAME_MAX + 1];
1293     } f;
1294   HANDLE dir = get_shared_parent_dir ();
1295   BOOLEAN restart = TRUE;
1296
1297   do
1298     {
1299       status = NtQueryDirectoryObject (dir, &f, sizeof f, TRUE, restart,
1300                                        &context, NULL);
1301       if (NT_SUCCESS (status))
1302         {
1303           restart = FALSE;
1304           f.dbi.ObjectName.Buffer[f.dbi.ObjectName.Length / sizeof (WCHAR)]
1305             = L'\0';
1306           if (wcsncmp (f.dbi.ObjectName.Buffer, L"cygpid.", 7) == 0)
1307             {
1308               DWORD pid = wcstoul (f.dbi.ObjectName.Buffer + 7, NULL, 10);
1309               add (nelem, false, pid);
1310             }
1311         }
1312     }
1313   while (NT_SUCCESS (status));
1314   cygwin_pid_nelem = nelem;
1315
1316   if (winpid)
1317     {
1318       static DWORD szprocs;
1319       static PSYSTEM_PROCESSES procs;
1320
1321       if (!szprocs)
1322         {
1323           procs = (PSYSTEM_PROCESSES)
1324                   malloc (sizeof (*procs) + (szprocs = 200 * sizeof (*procs)));
1325           if (!procs)
1326             {
1327               system_printf ("out of memory reading system process "
1328                              "information");
1329               return 0;
1330             }
1331         }
1332
1333       for (;;)
1334         {
1335           status =
1336                 NtQuerySystemInformation (SystemProcessesAndThreadsInformation,
1337                                           procs, szprocs, NULL);
1338           if (NT_SUCCESS (status))
1339             break;
1340
1341           if (status == STATUS_INFO_LENGTH_MISMATCH)
1342             {
1343               PSYSTEM_PROCESSES new_p;
1344
1345               new_p = (PSYSTEM_PROCESSES)
1346                       realloc (procs, szprocs += 200 * sizeof (*procs));
1347               if (!new_p)
1348                 {
1349                   system_printf ("out of memory reading system process "
1350                                  "information");
1351                   return 0;
1352                 }
1353               procs = new_p;
1354             }
1355           else
1356             {
1357               system_printf ("error %p reading system process information",
1358                              status);
1359               return 0;
1360             }
1361         }
1362
1363       PSYSTEM_PROCESSES px = procs;
1364       for (;;)
1365         {
1366           if (px->ProcessId)
1367             {
1368               bool do_add = true;
1369               for (unsigned i = 0; i < cygwin_pid_nelem; ++i)
1370                 if (pidlist[i] == px->ProcessId)
1371                   {
1372                     do_add = false;
1373                     break;
1374                   }
1375               if (do_add)
1376                 add (nelem, true, px->ProcessId);
1377             }
1378           if (!px->NextEntryDelta)
1379             break;
1380           px = (PSYSTEM_PROCESSES) ((char *) px + px->NextEntryDelta);
1381         }
1382     }
1383
1384   return nelem;
1385 }
1386
1387 void
1388 winpids::set (bool winpid)
1389 {
1390   __malloc_lock ();
1391   npids = enum_processes (winpid);
1392   if (pidlist)
1393     pidlist[npids] = 0;
1394   __malloc_unlock ();
1395 }
1396
1397 DWORD
1398 winpids::enum_init (bool winpid)
1399 {
1400   return enum_processes (winpid);
1401 }
1402
1403 void
1404 winpids::release ()
1405 {
1406   _pinfo *p;
1407   for (unsigned i = 0; i < npids; i++)
1408     if (pinfolist[i] == (_pinfo *) myself)
1409       continue;
1410     else if (pinfolist[i].hProcess)
1411       pinfolist[i].release ();
1412     else if ((p = pinfolist[i]))
1413       {
1414         pinfolist[i].procinfo = NULL;
1415         free (p);
1416       }
1417 }
1418
1419 winpids::~winpids ()
1420 {
1421   if (npidlist)
1422     {
1423       release ();
1424       free (pidlist);
1425       free (pinfolist);
1426     }
1427 }