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