1 /* pinfo.cc: process table support
3 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
13 #include "miscfuncs.h"
22 #include "perprocess.h"
26 #include "shared_info.h"
28 #include "cygmalloc.h"
31 #include "child_info.h"
33 class pinfo_basic: public _pinfo
39 pinfo_basic::pinfo_basic()
41 pid = dwProcessId = GetCurrentProcessId ();
42 GetModuleFileNameW (NULL, progname, sizeof (progname));
45 pinfo_basic myself_initial NO_COPY;
47 pinfo NO_COPY myself (static_cast<_pinfo *> (&myself_initial)); // Avoid myself != NULL checks
49 bool is_toplevel_proc;
51 /* Setup the pinfo structure for this process. There may already be a
52 _pinfo for this "pid" if h != NULL. */
55 pinfo::thisproc (HANDLE h)
60 cygheap->pid = cygwin_pid (myself_initial.pid);
62 init (cygheap->pid, PID_IN_USE, h ?: INVALID_HANDLE_VALUE);
63 procinfo->process_state |= PID_IN_USE;
64 procinfo->dwProcessId = myself_initial.pid;
65 procinfo->sendsig = myself_initial.sendsig;
66 wcscpy (procinfo->progname, myself_initial.progname);
68 debug_printf ("myself->dwProcessId %u", procinfo->dwProcessId);
72 static pinfo NO_COPY myself_identity;
73 myself_identity.init (cygwin_pid (procinfo->dwProcessId), PID_EXECED, NULL);
74 procinfo->exec_sendsig = NULL;
75 procinfo->exec_dwProcessId = 0;
77 else if (!child_proc_info) /* child_proc_info is only set when this process
78 was started by another cygwin process */
79 procinfo->start_time = time (NULL); /* Register our starting time. */
80 else if (cygheap->pid_handle)
82 ForceCloseHandle (cygheap->pid_handle);
83 cygheap->pid_handle = NULL;
87 /* Initialize the process table entry for the current task.
88 This is not called for forked tasks, only execed ones. */
90 pinfo_init (char **envp, int envc)
94 environ_init (envp, envc);
95 /* spawn has already set up a pid structure for us so we'll use that */
96 myself->process_state |= PID_CYGPARENT;
100 /* Invent our own pid. */
102 myself.thisproc (NULL);
104 myself->pgid = myself->sid = myself->pid;
106 myself->uid = ILLEGAL_UID;
107 myself->gid = UNKNOWN_GID;
108 environ_init (NULL, 0); /* call after myself has been set up */
109 myself->nice = winprio_to_nice (GetPriorityClass (GetCurrentProcess ()));
110 debug_printf ("Set nice to %d", myself->nice);
113 myself->process_state |= PID_ACTIVE;
114 myself->process_state &= ~(PID_INITIALIZING | PID_EXITED);
115 debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
119 status_exit (DWORD x)
121 const char *find_first_notloaded_dll (path_conv &);
124 case STATUS_DLL_NOT_FOUND:
126 char posix_prog[NT_MAX_PATH];
128 RtlInitUnicodeString(&uc, myself->progname);
129 path_conv pc (&uc, PC_NOWARN);
130 mount_table->conv_to_posix_path (pc.get_win32 (), posix_prog, 1);
131 small_printf ("%s: error while loading shared libraries: %s: cannot open shared object file: No such file or directory\n",
132 posix_prog, find_first_notloaded_dll (pc));
136 case STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION: /* custom error value */
137 /* We've already printed the error message in pseudo-reloc.c */
146 # define self (*this)
148 pinfo::set_exit_code (DWORD x)
150 if (x >= 0xc0000000UL)
152 self->exitcode = EXITCODE_SET | (sigExeced ?: (x & 0xff) << 8);
156 pinfo::maybe_set_exit_code_from_windows ()
158 DWORD x = 0xdeadbeef;
159 DWORD oexitcode = self->exitcode;
161 if (hProcess && !(self->exitcode & EXITCODE_SET))
163 WaitForSingleObject (hProcess, INFINITE); /* just to be safe, in case
164 process hasn't quite exited
165 after closing pipe */
166 GetExitCodeProcess (hProcess, &x);
169 sigproc_printf ("pid %d, exit value - old %p, windows %p, cygwin %p",
170 self->pid, oexitcode, x, self->exitcode);
174 pinfo::exit (DWORD n)
176 minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
177 lock_process until_exit ();
178 cygthread::terminate ();
180 if (n != EXITCODE_NOSET)
181 self->exitcode = EXITCODE_SET | n;/* We're really exiting. Record the UNIX exit code. */
184 exit_state = ES_EXEC_EXIT;
185 maybe_set_exit_code_from_windows ();
188 sigproc_terminate (ES_FINAL);
190 /* FIXME: There is a potential race between an execed process and its
191 parent here. I hated to add a mutex just for that, though. */
193 fill_rusage (&r, GetCurrentProcess ());
194 add_rusage (&self->rusage_self, &r);
195 int exitcode = self->exitcode & 0xffff;
196 if (!self->cygstarted)
197 exitcode = ((exitcode & 0xff) << 8) | ((exitcode >> 8) & 0xff);
198 sigproc_printf ("Calling ExitProcess n %p, exitcode %p", n, exitcode);
199 ExitProcess (exitcode);
204 pinfo::init (pid_t n, DWORD flag, HANDLE h0)
206 shared_locations shloc;
208 if (myself && !(flag & PID_EXECED)
209 && (n == myself->pid || (DWORD) n == myself->dwProcessId))
217 int createit = flag & (PID_IN_USE | PID_EXECED);
218 DWORD access = FILE_MAP_READ
219 | (flag & (PID_IN_USE | PID_EXECED | PID_MAP_RW)
220 ? FILE_MAP_WRITE : 0);
222 shloc = (flag & (PID_IN_USE | PID_EXECED)) ? SH_JUSTCREATE : SH_JUSTOPEN;
226 if (h0 == INVALID_HANDLE_VALUE)
231 PSECURITY_ATTRIBUTES sa_buf = (PSECURITY_ATTRIBUTES) alloca (1024);
232 PSECURITY_ATTRIBUTES sec_attribs = sec_user_nih (sa_buf, cygheap->user.sid(),
233 well_known_world_sid,
236 for (int i = 0; i < 20; i++)
239 if (flag & PID_EXECED)
240 mapsize = PINFO_REDIR_SIZE;
242 mapsize = sizeof (_pinfo);
244 procinfo = (_pinfo *) open_shared (L"cygpid", n, h0, mapsize, &shloc,
245 sec_attribs, access);
258 switch (GetLastError ())
260 case ERROR_INVALID_HANDLE:
261 api_fatal ("MapViewOfFileEx h0 %p, i %d failed, %E", h0, i);
262 case ERROR_INVALID_ADDRESS:
265 debug_printf ("MapViewOfFileEx h0 %p, i %d failed, %E", h0, i);
270 bool created = shloc != SH_JUSTOPEN;
272 if ((procinfo->process_state & PID_INITIALIZING) && (flag & PID_NOREDIR)
273 && cygwin_pid (procinfo->dwProcessId) != procinfo->pid)
279 if (procinfo->process_state & PID_EXECED)
282 pid_t realpid = procinfo->pid;
283 debug_printf ("execed process windows pid %d, cygwin pid %d", n, realpid);
285 api_fatal ("retrieval of execed process info for pid %d failed due to recursion.", n);
293 /* In certain pathological cases, it is possible for the shared memory
294 region to exist for a while after a process has exited. This should
295 only be a brief occurrence, so rather than introduce some kind of
296 locking mechanism, just loop. */
297 if (!created && createit && (procinfo->process_state & PID_EXITED))
299 debug_printf ("looping because pid %d, procinfo->pid %d, "
300 "procinfo->dwProcessid %u has PID_EXITED set",
301 n, procinfo->pid, procinfo->dwProcessId);
307 else if (!(flag & PID_EXECED))
311 procinfo->process_state |= PID_IN_USE | PID_EXECED;
312 procinfo->pid = myself->pid;
315 h = h0; /* Success! */
327 ProtectHandle1 (h, pinfo_shared_handle);
339 PACL acl_buf = (PACL) alloca (1024);
340 SECURITY_DESCRIPTOR sd;
343 sec_acl (acl_buf, true, true, cygheap->user.sid (),
344 well_known_world_sid, FILE_MAP_READ);
345 if (!InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION))
346 debug_printf ("InitializeSecurityDescriptor %E");
347 else if (!SetSecurityDescriptorDacl (&sd, TRUE, acl_buf, FALSE))
348 debug_printf ("SetSecurityDescriptorDacl %E");
349 else if ((status = NtSetSecurityObject (h, DACL_SECURITY_INFORMATION, &sd)))
350 debug_printf ("NtSetSecurityObject %lx", status);
354 _pinfo::_ctty (char *buf)
356 if (ctty == TTY_CONSOLE)
357 strcpy (buf, "ctty /dev/console");
359 strcpy (buf, "no ctty");
361 __small_sprintf (buf, "ctty /dev/tty%d", ctty);
366 _pinfo::set_ctty (tty_min *tc, int flags, fhandler_tty_slave *arch)
368 debug_printf ("old %s", __ctty ());
369 if ((ctty < 0 || ctty == tc->ntty) && !(flags & O_NOCTTY))
373 syscall_printf ("attaching %s sid %d, pid %d, pgid %d, tty->pgid %d, tty->sid %d",
374 __ctty (), sid, pid, pgid, tc->getpgid (), tc->getsid ());
376 pinfo p (tc->getsid ());
377 if (sid == pid && (!p || p->pid == pid || !p->exists ()))
380 debug_printf ("resetting %s sid. Was %d, now %d. pgid was %d, now %d.",
381 __ctty (), tc->getsid (), sid, tc->getpgid (), pgid);
383 paranoid_printf ("resetting %s sid. Was %d, now %d. pgid was %d, now %d.",
384 __ctty (), tc->getsid (), sid, tc->getpgid (), pgid);
386 /* We are the session leader */
392 if (tc->getpgid () == 0)
393 {debug_printf ("setting pgid to %d", pgid);
396 if (cygheap->ctty != arch)
398 debug_printf ("cygheap->ctty %p, arch %p", cygheap->ctty, arch);
400 syscall_printf ("ctty NULL");
403 syscall_printf ("ctty %p, usecount %d", cygheap->ctty,
404 cygheap->ctty->usecount);
405 cygheap->ctty->close ();
407 cygheap->ctty = arch;
411 /* guard ctty arch */
412 cygheap->manage_console_count ("_pinfo::set_ctty", 1);
413 report_tty_counts (cygheap->ctty, "ctty", "");
419 /* Test to determine if a process really exists and is processing signals.
424 return this && !(process_state & PID_EXITED);
430 HANDLE h = OpenProcess (PROCESS_QUERY_INFORMATION, false, dwProcessId);
437 commune_process (void *arg)
439 siginfo_t& si = *((siginfo_t *) arg);
441 char *path = tp.c_get ();
443 HANDLE& tothem = si._si_commune._si_write_handle;
444 HANDLE process_sync =
445 OpenSemaphore (SYNCHRONIZE, false, shared_name (path, "commune", si.si_pid));
446 if (process_sync) // FIXME: this test shouldn't be necessary
447 ProtectHandle (process_sync);
450 if (si._si_commune._si_code & PICOM_EXTRASTR)
451 si._si_commune._si_str = (char *) (&si + 1);
453 switch (si._si_commune._si_code)
457 sigproc_printf ("processing PICOM_CMDLINE");
459 const char *argv[__argc_safe + 1];
461 for (int i = 0; i < __argc_safe; i++)
463 if (IsBadStringPtr (__argv[i], INT32_MAX))
467 n += strlen (argv[i]) + 1;
469 argv[__argc_safe] = NULL;
470 if (!WriteFile (tothem, &n, sizeof n, &nr, NULL))
472 /*__seterrno ();*/ // this is run from the signal thread, so don't set errno
473 sigproc_printf ("WriteFile sizeof argv failed, %E");
476 for (const char **a = argv; *a; a++)
477 if (!WriteFile (tothem, *a, strlen (*a) + 1, &nr, NULL))
479 sigproc_printf ("WriteFile arg %d failed, %E", a - argv);
486 sigproc_printf ("processing PICOM_CWD");
487 unsigned int n = strlen (cygheap->cwd.get (path, 1, 1, NT_MAX_PATH)) + 1;
488 if (!WriteFile (tothem, &n, sizeof n, &nr, NULL))
489 sigproc_printf ("WriteFile sizeof cwd failed, %E");
490 else if (!WriteFile (tothem, path, n, &nr, NULL))
491 sigproc_printf ("WriteFile cwd failed, %E");
496 sigproc_printf ("processing PICOM_ROOT");
498 if (cygheap->root.exists ())
499 n = strlen (strcpy (path, cygheap->root.posix_path ())) + 1;
501 n = strlen (strcpy (path, "/")) + 1;
502 if (!WriteFile (tothem, &n, sizeof n, &nr, NULL))
503 sigproc_printf ("WriteFile sizeof root failed, %E");
504 else if (!WriteFile (tothem, path, n, &nr, NULL))
505 sigproc_printf ("WriteFile root failed, %E");
510 sigproc_printf ("processing PICOM_FDS");
514 while ((fd = cfd.next ()) >= 0)
517 if (!WriteFile (tothem, &n, sizeof n, &nr, NULL))
518 sigproc_printf ("WriteFile sizeof fds failed, %E");
520 while ((fd = cfd.next ()) >= 0)
521 if (!WriteFile (tothem, &fd, sizeof fd, &nr, NULL))
523 sigproc_printf ("WriteFile fd %d failed, %E", fd);
528 case PICOM_PIPE_FHANDLER:
530 sigproc_printf ("processing PICOM_FDS");
531 HANDLE hdl = si._si_commune._si_pipe_fhandler;
534 while (cfd.next () >= 0)
535 if (cfd->get_handle () == hdl)
537 fhandler_pipe *fh = cfd;
539 if (!WriteFile (tothem, &n, sizeof n, &nr, NULL))
540 sigproc_printf ("WriteFile sizeof hdl failed, %E");
541 else if (!WriteFile (tothem, fh, n, &nr, NULL))
542 sigproc_printf ("WriteFile hdl failed, %E");
545 if (!n && !WriteFile (tothem, &n, sizeof n, &nr, NULL))
546 sigproc_printf ("WriteFile sizeof hdl failed, %E");
551 sigproc_printf ("processing PICOM_FD");
552 int fd = si._si_commune._si_fd;
554 cygheap_fdget cfd (fd);
556 n = strlen (strcpy (path, "")) + 1;
558 n = strlen (cfd->get_proc_fd_name (path)) + 1;
559 if (!WriteFile (tothem, &n, sizeof n, &nr, NULL))
560 sigproc_printf ("WriteFile sizeof fd failed, %E");
561 else if (!WriteFile (tothem, path, n, &nr, NULL))
562 sigproc_printf ("WriteFile fd failed, %E");
568 DWORD res = WaitForSingleObject (process_sync, 5000);
569 if (res != WAIT_OBJECT_0)
570 sigproc_printf ("WFSO failed - %d, %E", res);
572 sigproc_printf ("synchronized with pid %d", si.si_pid);
573 ForceCloseHandle (process_sync);
575 CloseHandle (tothem);
576 _my_tls._ctinfo->auto_release ();
581 _pinfo::commune_request (__uint32_t code, ...)
587 HANDLE& hp = si._si_commune._si_process_handle;
588 HANDLE& fromthem = si._si_commune._si_read_handle;
589 HANDLE request_sync = NULL;
601 va_start (args, code);
602 si._si_commune._si_code = code;
605 case PICOM_PIPE_FHANDLER:
606 si._si_commune._si_pipe_fhandler = va_arg (args, HANDLE);
610 si._si_commune._si_fd = va_arg (args, int);
618 char name_buf[MAX_PATH];
619 request_sync = CreateSemaphore (&sec_none_nih, 0, LONG_MAX,
620 shared_name (name_buf, "commune", myself->pid));
623 ProtectHandle (request_sync);
625 si.si_signo = __SIGCOMMUNE;
626 if (sig_send (this, si))
628 ForceCloseHandle (request_sync); /* don't signal semaphore since there was apparently no receiving process */
641 case PICOM_PIPE_FHANDLER:
642 if (!ReadFile (fromthem, &n, sizeof n, &nr, NULL) || nr != sizeof n)
651 res.s = (char *) cmalloc_abort (HEAP_COMMUNE, n);
653 for (p = res.s; n && ReadFile (fromthem, p, n, &nr, NULL); p += nr, n -= nr)
667 memset (&res, 0, sizeof (res));
673 ReleaseSemaphore (request_sync, 1, &res);
674 ForceCloseHandle (request_sync);
679 CloseHandle (fromthem);
684 _pinfo::pipe_fhandler (HANDLE hdl, size_t &n)
688 if (pid == myself->pid)
690 commune_result cr = commune_request (PICOM_PIPE_FHANDLER, hdl);
692 return (fhandler_pipe *) cr.s;
696 _pinfo::fd (int fd, size_t &n)
701 if (pid != myself->pid)
703 commune_result cr = commune_request (PICOM_FD, fd);
709 cygheap_fdget cfd (fd);
713 s = cfd->get_proc_fd_name ((char *) cmalloc_abort (HEAP_COMMUNE, NT_MAX_PATH));
720 _pinfo::fds (size_t &n)
725 if (pid != myself->pid)
727 commune_result cr = commune_request (PICOM_FDS);
735 cygheap_fdenum cfd (true);
736 while ((fd = cfd.next ()) >= 0)
739 s = (char *) cmalloc_abort (HEAP_COMMUNE, n);
741 while ((fd = cfd.next ()) >= 0 && (char *) p - s < (int) n)
748 _pinfo::root (size_t& n)
753 if (pid != myself->pid)
755 commune_result cr = commune_request (PICOM_ROOT);
761 if (cygheap->root.exists ())
762 s = cstrdup (cygheap->root.posix_path ());
771 _pinfo::cwd (size_t& n)
776 if (pid != myself->pid)
778 commune_result cr = commune_request (PICOM_CWD);
784 s = (char *) cmalloc_abort (HEAP_COMMUNE, NT_MAX_PATH);
785 cygheap->cwd.get (s, 1, 1, NT_MAX_PATH);
792 _pinfo::cmdline (size_t& n)
797 if (pid != myself->pid)
799 commune_result cr = commune_request (PICOM_CMDLINE);
806 for (char **a = __argv; *a; a++)
807 n += strlen (*a) + 1;
809 p = s = (char *) cmalloc_abort (HEAP_COMMUNE, n);
810 for (char **a = __argv; *a; a++)
813 p = strchr (p, '\0') + 1;
819 /* This is the workhorse which waits for the write end of the pipe
820 created during new process creation. If the pipe is closed or a zero
821 is received on the pipe, it is assumed that the cygwin pid has exited.
822 Otherwise, various "signals" can be sent to the parent to inform the
823 parent to perform a certain action. */
825 proc_waiter (void *arg)
827 pinfo vchild = *(pinfo *) arg;
828 ((pinfo *) arg)->waiter_ready = true;
831 si.si_signo = SIGCHLD;
832 si.si_code = CLD_EXITED;
833 si.si_pid = vchild->pid;
834 #if 0 // FIXME: This is tricky to get right
835 si.si_utime = pchildren[rc]->rusage_self.ru_utime;
836 si.si_stime = pchildren[rc].rusage_self.ru_stime;
838 pid_t pid = vchild->pid;
845 if (!ReadFile (vchild.rd_proc_pipe, &buf, 1, &nb, NULL)
846 && GetLastError () != ERROR_BROKEN_PIPE)
848 system_printf ("error on read of child wait pipe %p, %E", vchild.rd_proc_pipe);
852 si.si_uid = vchild->uid;
859 /* Child exited. Do some cleanup and signal myself. */
860 CloseHandle (vchild.rd_proc_pipe);
861 vchild.rd_proc_pipe = NULL;
862 vchild.maybe_set_exit_code_from_windows ();
863 if (WIFEXITED (vchild->exitcode))
864 si.si_code = CLD_EXITED;
865 else if (WCOREDUMP (vchild->exitcode))
866 si.si_code = CLD_DUMPED;
868 si.si_code = CLD_KILLED;
869 si.si_status = vchild->exitcode;
870 vchild->process_state = PID_EXITED;
871 /* This should always be last. Do not use vchild-> beyond this point */
877 if (ISSTATE (myself, PID_NOCLDSTOP)) // FIXME: No need for this flag to be in _pinfo any longer
879 /* Child stopped. Signal myself. */
880 si.si_code = CLD_STOPPED;
885 system_printf ("unknown value %d on proc pipe", buf);
889 /* Special case: If the "child process" that died is us, then we're
890 execing. Just call proc_subproc directly and then exit this loop.
894 /* execing. no signals available now. */
895 proc_subproc (PROC_CLEARWAIT, 0);
899 /* Send a SIGCHLD to myself. We do this here, rather than in proc_subproc
900 to avoid the proc_subproc lock since the signal thread will eventually
901 be calling proc_subproc and could unnecessarily block. */
902 sig_send (myself_nowait, si);
904 /* If we're just stopped or got a continue signal, keep looping.
905 Otherwise, return this thread to the pool. */
907 sigproc_printf ("looping");
912 sigproc_printf ("exiting wait thread for pid %d", pid);
913 vchild.wait_thread = NULL;
914 _my_tls._ctinfo->auto_release (); /* automatically return the cygthread to the cygthread pool */
919 _pinfo::dup_proc_pipe (HANDLE hProcess)
921 DWORD flags = DUPLICATE_SAME_ACCESS;
922 HANDLE orig_wr_proc_pipe = wr_proc_pipe;
923 /* Can't set DUPLICATE_CLOSE_SOURCE for exec case because we could be
924 execing a non-cygwin process and we need to set the exit value before the
926 if (this != myself || is_toplevel_proc)
927 flags |= DUPLICATE_CLOSE_SOURCE;
928 bool res = DuplicateHandle (GetCurrentProcess (), wr_proc_pipe,
929 hProcess, &wr_proc_pipe, 0, FALSE, flags);
930 if (!res && WaitForSingleObject (hProcess, 0) != WAIT_OBJECT_0)
932 wr_proc_pipe = orig_wr_proc_pipe;
933 system_printf ("DuplicateHandle failed, pid %d, hProcess %p, wr_proc_pipe %p, %E",
934 pid, hProcess, wr_proc_pipe);
938 wr_proc_pipe_owner = dwProcessId;
939 sigproc_printf ("duped wr_proc_pipe %p for pid %d(%u)", wr_proc_pipe,
942 return orig_wr_proc_pipe;
945 /* function to set up the process pipe and kick off proc_waiter */
949 /* FIXME: execed processes should be able to wait for pids that were started
950 by the process which execed them. */
951 if (!CreatePipe (&rd_proc_pipe, &((*this)->wr_proc_pipe), &sec_none_nih, 16))
953 system_printf ("Couldn't create pipe tracker for pid %d, %E",
958 if (!(*this)->dup_proc_pipe (hProcess))
960 system_printf ("Couldn't duplicate pipe topid %d(%p), %E", (*this)->pid, hProcess);
964 preserve (); /* Preserve the shared memory associated with the pinfo */
966 waiter_ready = false;
967 /* Fire up a new thread to track the subprocess */
968 cygthread *h = new cygthread (proc_waiter, this, "proc_waiter");
970 sigproc_printf ("tracking thread creation failed for pid %d", (*this)->pid);
974 sigproc_printf ("created tracking thread for pid %d, winpid %p, rd_pipe %p",
975 (*this)->pid, (*this)->dwProcessId, rd_proc_pipe);
982 _pinfo::sync_proc_pipe ()
984 if (wr_proc_pipe && wr_proc_pipe != INVALID_HANDLE_VALUE)
985 while (wr_proc_pipe_owner != GetCurrentProcessId ())
989 /* function to send a "signal" to the parent when something interesting happens
992 _pinfo::alert_parent (char sig)
996 /* Send something to our parent. If the parent has gone away, close the pipe.
997 Don't send if this is an exec stub.
999 FIXME: Is there a race here if we run this while another thread is attempting
1001 if (wr_proc_pipe == INVALID_HANDLE_VALUE || !myself->wr_proc_pipe || hExeced)
1006 if (WriteFile (wr_proc_pipe, &sig, 1, &nb, NULL))
1008 else if (GetLastError () != ERROR_BROKEN_PIPE)
1009 debug_printf ("sending %d notification to parent failed, %E", sig);
1013 HANDLE closeit = wr_proc_pipe;
1014 wr_proc_pipe = INVALID_HANDLE_VALUE;
1015 CloseHandle (closeit);
1026 void *unmap_procinfo = procinfo;
1028 UnmapViewOfFile (unmap_procinfo);
1034 ForceCloseHandle1 (close_h, pinfo_shared_handle);
1040 <sect1 id="func-cygwin-winpid-to-pid">
1041 <title>cygwin_winpid_to_pid</title>
1043 <funcsynopsis><funcprototype>
1044 <funcdef>extern "C" pid_t
1045 <function>cygwin_winpid_to_pid</function>
1047 <paramdef>int <parameter>winpid</parameter></paramdef>
1048 </funcprototype></funcsynopsis>
1050 <para>Given a windows pid, converts to the corresponding Cygwin
1051 pid, if any. Returns -1 if windows pid does not correspond to
1052 a cygwin pid.</para>
1054 <title>Example use of cygwin_winpid_to_pid</title>
1056 extern "C" cygwin_winpid_to_pid (int winpid);
1058 mypid = cygwin_winpid_to_pid (windows_pid);
1066 cygwin_winpid_to_pid (int winpid)
1068 pinfo p (cygwin_pid (winpid));
1077 #define slop_pidlist 200
1078 #define size_pidlist(i) (sizeof (pidlist[0]) * ((i) + 1))
1079 #define size_pinfolist(i) (sizeof (pinfolist[0]) * ((i) + 1))
1093 void no_close_p_handle () {h = NULL;}
1094 _onreturn (HANDLE& _h): h (&_h) {}
1098 winpids::add (DWORD& nelem, bool winpid, DWORD pid)
1100 pid_t cygpid = cygwin_pid (pid);
1102 if (nelem >= npidlist)
1104 npidlist += slop_pidlist;
1105 pidlist = (DWORD *) realloc (pidlist, size_pidlist (npidlist + 1));
1106 pinfolist = (pinfo *) realloc (pinfolist, size_pinfolist (npidlist + 1));
1109 pinfo& p = pinfolist[nelem];
1111 /* Open a the process to prevent a subsequent exit from invalidating the
1112 shared memory region. */
1113 p.hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, false, pid);
1114 _onreturn onreturn (p.hProcess);
1116 /* If we couldn't open the process then we don't have rights to it and should
1117 make a copy of the shared memory area if it exists (it may not).
1121 perform_copy = true;
1123 perform_copy = make_copy;
1125 p.init (cygpid, PID_NOREDIR | pinfo_access, NULL);
1127 /* If we're just looking for winpids then don't do any special cygwin "stuff* */
1131 /* !p means that we couldn't find shared memory for this pid. Probably means
1132 that it isn't a cygwin process. */
1137 p.init (cygpid, PID_NOREDIR, NULL);
1142 /* Scan list of previously recorded pids to make sure that this pid hasn't
1143 shown up before. This can happen when a process execs. */
1144 for (unsigned i = 0; i < nelem; i++)
1145 if (pinfolist[i]->pid == p->pid)
1147 if ((_pinfo *) p != (_pinfo *) myself)
1155 If p is "false" then, eventually any opened process handle will be closed and
1156 the function will exit without adding anything to the pid list.
1158 If p is "true" then we've discovered a cygwin process.
1160 Handle "myself" differently. Don't copy it and close/zero the handle we
1162 If not performing a copy, then keep the process handle open for the duration
1163 of the life of the procinfo region to potential races when a new process uses
1165 Otherwise, malloc some memory for a copy of the shared memory.
1167 If the malloc failed, then "oh well". Just keep the shared memory around
1168 and eventually close the handle when the winpids goes out of scope.
1170 If malloc succeeds, copy the procinfo we just grabbed into the new region,
1171 release the shared memory and allow the handle to be closed when this
1174 Oh, and add the pid to the list and bump the number of elements. */
1178 if (p == (_pinfo *) myself)
1179 /* handle specially. Close the handle but (eventually) don't
1180 deallocate procinfo in release call */;
1181 else if (!perform_copy)
1182 onreturn.no_close_p_handle (); /* Don't close the handle until release */
1185 _pinfo *pnew = (_pinfo *) malloc (sizeof (*p.procinfo));
1187 onreturn.no_close_p_handle ();
1190 *pnew = *p.procinfo;
1191 if ((_pinfo *) p != (_pinfo *) myself)
1199 pidlist[nelem++] = pid;
1203 winpids::enum_processes (bool winpid)
1205 static DWORD szprocs;
1206 static SYSTEM_PROCESSES *procs;
1210 procs = (SYSTEM_PROCESSES *) malloc (sizeof (*procs) + (szprocs = 200 * sizeof (*procs)));
1215 res = NtQuerySystemInformation (SystemProcessesAndThreadsInformation,
1216 procs, szprocs, NULL);
1220 if (res == STATUS_INFO_LENGTH_MISMATCH)
1221 procs = (SYSTEM_PROCESSES *) realloc (procs, szprocs += 200 * sizeof (*procs));
1224 system_printf ("error %p reading system process information", res);
1229 SYSTEM_PROCESSES *px = procs;
1233 add (nelem, winpid, px->ProcessId);
1234 if (!px->NextEntryDelta)
1236 px = (SYSTEM_PROCESSES *) ((char *) px + px->NextEntryDelta);
1243 winpids::set (bool winpid)
1246 npids = enum_processes (winpid);
1253 winpids::enum_init (bool winpid)
1255 return enum_processes (winpid);
1262 for (unsigned i = 0; i < npids; i++)
1263 if (pinfolist[i] == (_pinfo *) myself)
1265 else if (pinfolist[i].hProcess)
1268 pinfolist[i].release ();
1269 CloseHandle (pinfolist[i].hProcess);
1271 else if ((p = pinfolist[i]))
1273 pinfolist[i].procinfo = NULL;
1278 winpids::~winpids ()