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