aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/dcrt0.cc27
-rw-r--r--winsup/cygwin/fork.cc33
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/include/sys/cygwin.h3
-rw-r--r--winsup/cygwin/pinfo.cc212
-rw-r--r--winsup/cygwin/pinfo.h22
-rw-r--r--winsup/cygwin/release/3.03
-rw-r--r--winsup/cygwin/shared.cc5
-rw-r--r--winsup/cygwin/shared_info.h3
-rw-r--r--winsup/cygwin/spawn.cc2
10 files changed, 157 insertions, 156 deletions
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 463df31..5cdf01c 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -687,28 +687,11 @@ child_info_spawn::handle_spawn ()
if (child_proc_info->parent)
{
- if (type == _CH_EXEC)
- {
- /* Keep pointer to parent open if we've execed so that pid will not be
- reused. Try to Urther reduce permissions. */
- HANDLE new_parent;
-
- if (DuplicateHandle (GetCurrentProcess (), child_proc_info->parent,
- GetCurrentProcess (), &new_parent,
- SYNCHRONIZE, FALSE, 0))
- {
- CloseHandle (child_proc_info->parent);
- child_proc_info->parent = new_parent;
- }
- }
- else
- {
- /* Otherwise, we no longer need this handle so close it. Need to do
- this after debug_fixup_after_fork_exec or DEBUGGING handling of
- handles might get confused. */
- CloseHandle (child_proc_info->parent);
- child_proc_info->parent = NULL;
- }
+ /* We no longer need this handle so close it. Need to do
+ this after debug_fixup_after_fork_exec or DEBUGGING handling of
+ handles might get confused. */
+ CloseHandle (child_proc_info->parent);
+ child_proc_info->parent = NULL;
}
signal_fixup_after_exec ();
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index d8c4ac4..c083f7a 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -209,35 +209,6 @@ frok::child (volatile char * volatile here)
return 0;
}
-#define NO_SLOW_PID_REUSE
-#ifndef NO_SLOW_PID_REUSE
-static void
-slow_pid_reuse (HANDLE h)
-{
- static NO_COPY HANDLE last_fork_procs[NPIDS_HELD];
- static NO_COPY unsigned nfork_procs;
-
- if (nfork_procs >= (sizeof (last_fork_procs) / sizeof (last_fork_procs [0])))
- nfork_procs = 0;
- /* Keep a list of handles to child processes sitting around to prevent
- Windows from reusing the same pid n times in a row. Having the same pids
- close in succesion confuses bash. Keeping a handle open will stop
- windows from reusing the same pid. */
- if (last_fork_procs[nfork_procs])
- ForceCloseHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
- if (DuplicateHandle (GetCurrentProcess (), h,
- GetCurrentProcess (), &last_fork_procs[nfork_procs],
- 0, FALSE, DUPLICATE_SAME_ACCESS))
- ProtectHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
- else
- {
- last_fork_procs[nfork_procs] = NULL;
- system_printf ("couldn't create last_fork_proc, %E");
- }
- nfork_procs++;
-}
-#endif
-
int __stdcall
frok::parent (volatile char * volatile stack_here)
{
@@ -437,10 +408,6 @@ frok::parent (volatile char * volatile stack_here)
goto cleanup;
}
-#ifndef NO_SLOW_PID_REUSE
- slow_pid_reuse (hchild);
-#endif
-
/* CHILD IS STOPPED */
debug_printf ("child is alive (but stopped)");
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index b5ba93f..8926d49 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -506,12 +506,13 @@ details. */
333: Add timerfd_create, timerfd_gettime, timerfd_settime.
334: Remove matherr.
335: Change size of utsname, change uname output.
+ 336: New Cygwin PID algorithm (yeah, not really an API change)
Note that we forgot to bump the api for ualarm, strtoll, strtoull,
sigaltstack, sethostname. */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 335
+#define CYGWIN_VERSION_API_MINOR 336
/* There is also a compatibity version number associated with the shared memory
regions. It is incremented when incompatible changes are made to the shared
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index c5da87c..480d8ea 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -269,8 +269,7 @@ enum
PID_INITIALIZING = 0x00800, /* Set until ready to receive signals. */
PID_NEW = 0x01000, /* Available. */
PID_ALLPIDS = 0x02000, /* used by pinfo scanner */
- PID_EXECED = 0x04000, /* redirect to original pid info block */
- PID_NOREDIR = 0x08000, /* don't redirect if execed */
+ PID_PROCINFO = 0x08000, /* caller just asks for process info */
PID_EXITED = 0x40000000, /* Free entry. */
PID_REAPED = 0x80000000 /* Reaped */
};
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 90dfd2b..98168c7 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -58,8 +58,7 @@ pinfo::thisproc (HANDLE h)
DWORD flags = PID_IN_USE | PID_ACTIVE;
if (!h)
{
- h = INVALID_HANDLE_VALUE;
- cygheap->pid = cygwin_pid (myself_initial.pid);
+ cygheap->pid = create_cygwin_pid ();
flags |= PID_NEW;
}
@@ -68,16 +67,10 @@ pinfo::thisproc (HANDLE h)
procinfo->dwProcessId = myself_initial.pid;
procinfo->sendsig = myself_initial.sendsig;
wcscpy (procinfo->progname, myself_initial.progname);
+ create_winpid_symlink (procinfo->pid, procinfo->dwProcessId);
+ procinfo->exec_sendsig = NULL;
+ procinfo->exec_dwProcessId = 0;
debug_printf ("myself dwProcessId %u", procinfo->dwProcessId);
- if (h != INVALID_HANDLE_VALUE)
- {
- /* here if execed */
- static pinfo NO_COPY myself_identity;
- myself_identity.init (cygwin_pid (procinfo->dwProcessId), PID_EXECED, NULL);
- procinfo->exec_sendsig = NULL;
- procinfo->exec_dwProcessId = 0;
- myself_identity->ppid = procinfo->pid;
- }
}
/* Initialize the process table entry for the current task.
@@ -109,7 +102,8 @@ pinfo_init (char **envp, int envc)
myself->process_state |= PID_ACTIVE;
myself->process_state &= ~(PID_INITIALIZING | PID_EXITED | PID_REAPED);
myself.preserve ();
- debug_printf ("pid %d, pgid %d, process_state %y", myself->pid, myself->pgid, myself->process_state);
+ debug_printf ("pid %d, pgid %d, process_state %y",
+ myself->pid, myself->pgid, myself->process_state);
}
DWORD
@@ -152,7 +146,7 @@ pinfo::status_exit (DWORD x)
reason (but note, the environment *in* CMD is broken and shortened).
This occurs at a point where there's no return to the exec'ing parent
process, so we have to find some way to inform the user what happened.
-
+
FIXME: For now, just return with SIGBUS set. Maybe it's better to add
a lengthy small_printf instead. */
x = SIGBUS;
@@ -229,6 +223,106 @@ pinfo::exit (DWORD n)
}
# undef self
+/* Return next free Cygwin PID between 2 and 65535, round-robin. Each new
+ PID is checked that it doesn't collide with an existing PID. For that,
+ just check if the "cygpid.PID" section exists. */
+pid_t
+create_cygwin_pid ()
+{
+ pid_t pid = 0;
+ WCHAR sym_name[24];
+ UNICODE_STRING sym_str;
+ OBJECT_ATTRIBUTES attr;
+ HANDLE sym_hdl;
+ NTSTATUS status;
+
+ do
+ {
+ do
+ {
+ pid = ((uint32_t) InterlockedIncrement (&cygwin_shared->pid_src))
+ % 65536;
+ }
+ while (pid < 2);
+ __small_swprintf (sym_name, L"cygpid.%u", pid);
+ RtlInitUnicodeString (&sym_str, sym_name);
+ InitializeObjectAttributes (&attr, &sym_str, OBJ_CASE_INSENSITIVE,
+ get_shared_parent_dir (), NULL);
+ /* We just want to know if the section (and thus the process) still
+ exists. Instead of actually opening the section, try to open
+ it as symlink. NtOpenSymbolicLinkObject will always returns an
+ error:
+ - STATUS_OBJECT_NAME_NOT_FOUND if the section doesn't exist,
+ so the slot is free and we can use this pid.
+ - STATUS_OBJECT_TYPE_MISMATCH if the section exists, so we have
+ to skip this pid and loop to try the next one.
+ As side-effect we never have to close the section handle and thus
+ we don't influence the lifetime of the section. */
+ status = NtOpenSymbolicLinkObject (&sym_hdl, SYMBOLIC_LINK_QUERY, &attr);
+ }
+ while (status == STATUS_OBJECT_TYPE_MISMATCH);
+ return pid;
+}
+
+/* Convert Windows WINPID into Cygwin PID. Utilize the "winpid.WINPID"
+ symlinks created for each process. The symlink contains the Cygwin
+ PID as target. Return 0 if no "winpid.WINPID" symlink exists for
+ this WINPID. */
+pid_t
+cygwin_pid (DWORD dwProcessId)
+{
+ WCHAR sym_name[24];
+ WCHAR pid_name[12];
+ UNICODE_STRING sym_str;
+ UNICODE_STRING pid_str;
+ OBJECT_ATTRIBUTES attr;
+ HANDLE sym_hdl;
+ NTSTATUS status;
+
+ __small_swprintf (sym_name, L"winpid.%u", dwProcessId);
+ RtlInitUnicodeString (&sym_str, sym_name);
+ InitializeObjectAttributes (&attr, &sym_str, OBJ_CASE_INSENSITIVE,
+ get_shared_parent_dir (), NULL);
+ status = NtOpenSymbolicLinkObject (&sym_hdl, SYMBOLIC_LINK_QUERY, &attr);
+ if (!NT_SUCCESS (status))
+ return 0;
+ RtlInitEmptyUnicodeString (&pid_str, pid_name,
+ sizeof pid_name - sizeof (WCHAR));
+ status = NtQuerySymbolicLinkObject (sym_hdl, &pid_str, NULL);
+ NtClose (sym_hdl);
+ if (!NT_SUCCESS (status))
+ {
+ system_printf ("NtOpenSymbolicLinkObject: %y, PID %u, ret 0",
+ status, dwProcessId);
+ return 0;
+ }
+ pid_str.Buffer[pid_str.Length / sizeof (WCHAR)] = L'\0';
+ pid_t ret = (pid_t) wcstoul (pid_str.Buffer, NULL, 10);
+ return ret;
+}
+
+/* Create "winpid.WINPID" symlinks with the Cygwin PID of that process as
+ target. This is used to find the Cygwin PID for a given Windows WINPID. */
+inline void
+pinfo::create_winpid_symlink (pid_t cygpid, DWORD winpid)
+{
+ WCHAR sym_name[24];
+ WCHAR pid_name[24];
+ UNICODE_STRING sym_str;
+ UNICODE_STRING pid_str;
+ OBJECT_ATTRIBUTES attr;
+
+ __small_swprintf (sym_name, L"winpid.%u",
+ procinfo->dwProcessId ?: myself_initial.pid);
+ RtlInitUnicodeString (&sym_str, sym_name);
+ __small_swprintf (pid_name, L"%u", procinfo->pid);
+ RtlInitUnicodeString (&pid_str, pid_name);
+ InitializeObjectAttributes (&attr, &sym_str, OBJ_CASE_INSENSITIVE,
+ get_shared_parent_dir (), NULL);
+ NtCreateSymbolicLinkObject (&winpid_hdl, SYMBOLIC_LINK_ALL_ACCESS,
+ &attr, &pid_str);
+}
+
inline void
pinfo::_pinfo_release ()
{
@@ -252,20 +346,18 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
{
shared_locations shloc;
h = NULL;
- if (myself && !(flag & PID_EXECED)
- && (n == myself->pid || (DWORD) n == myself->dwProcessId))
+ if (myself && n == myself->pid)
{
procinfo = myself;
destroy = 0;
return;
}
- int createit = flag & (PID_IN_USE | PID_EXECED);
+ int createit = (flag & PID_IN_USE);
DWORD access = FILE_MAP_READ
- | (flag & (PID_IN_USE | PID_EXECED | PID_MAP_RW)
- ? FILE_MAP_WRITE : 0);
+ | (flag & (PID_IN_USE | PID_MAP_RW) ? FILE_MAP_WRITE : 0);
if (!h0 || myself.h)
- shloc = (flag & (PID_IN_USE | PID_EXECED)) ? SH_JUSTCREATE : SH_JUSTOPEN;
+ shloc = (flag & PID_IN_USE) ? SH_JUSTCREATE : SH_JUSTOPEN;
else
{
shloc = SH_MYSELF;
@@ -281,14 +373,8 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
for (int i = 0; i < 20; i++)
{
- DWORD mapsize;
- if (flag & PID_EXECED)
- mapsize = PINFO_REDIR_SIZE;
- else
- mapsize = sizeof (_pinfo);
-
- procinfo = (_pinfo *) open_shared (L"cygpid", n, h0, mapsize, &shloc,
- sec_attribs, access);
+ procinfo = (_pinfo *) open_shared (L"cygpid", n, h0, sizeof (_pinfo),
+ &shloc, sec_attribs, access);
if (!h0)
{
if (createit)
@@ -311,33 +397,10 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
bool created = shloc != SH_JUSTOPEN;
- /* Detect situation where a transitional memory block is being retrieved.
- If the block has been allocated with PINFO_REDIR_SIZE but not yet
- updated with a PID_EXECED state then we'll retry. */
- if (!created && !(flag & PID_NEW) && !procinfo->ppid)
- {
- /* Fetching process info for /proc or ps? just ignore this one. */
- if (flag & PID_NOREDIR)
- break;
- /* FIXME: Do we ever hit this case? And if so, in what situation? */
- system_printf ("This shouldn't happen:\n"
- " me: (%d, %d, %d, %W)\n"
- " pid %d\n"
- " process_state %y\n"
- " cygstarted %d\n"
- " dwProcessId %d\n"
- " name %W",
- myself->pid, myself->dwProcessId, myself->cygstarted,
- myself->progname,
- procinfo->pid, procinfo->process_state,
- procinfo->cygstarted, procinfo->dwProcessId,
- procinfo->progname);
- /* If not populated, wait 2 seconds for procinfo to become populated.
- Would like to wait with finer granularity but that is not easily
- doable. */
- for (int i = 0; i < 200 && !procinfo->ppid; i++)
- Sleep (10);
- }
+ /* Just fetching info for ps or /proc, don't do anything rash. */
+ if (!created && !(flag & PID_NEW) && !procinfo->ppid
+ && (flag & PID_PROCINFO))
+ break;
if (!created && createit && (procinfo->process_state & PID_REAPED))
{
@@ -346,32 +409,18 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
shared memory */
}
- if ((procinfo->process_state & PID_REAPED)
- || ((procinfo->process_state & PID_INITIALIZING) && (flag & PID_NOREDIR)
- && cygwin_pid (procinfo->dwProcessId) != procinfo->pid))
+ if (procinfo->process_state & PID_REAPED)
{
set_errno (ESRCH);
break;
}
- if (procinfo->process_state & PID_EXECED)
- {
- pid_t realpid = procinfo->pid;
- debug_printf ("execed process windows pid %u, cygwin pid %d", n, realpid);
- if (realpid == n)
- api_fatal ("retrieval of execed process info for pid %d failed due to recursion.", n);
-
- n = realpid;
- CloseHandle (h0);
- h0 = NULL;
- goto loop;
- }
-
/* In certain pathological cases, it is possible for the shared memory
region to exist for a while after a process has exited. This should
only be a brief occurrence, so rather than introduce some kind of
locking mechanism, just loop. */
- if (!created && createit && (procinfo->process_state & (PID_EXITED | PID_REAPED)))
+ if (!created && createit
+ && (procinfo->process_state & (PID_EXITED | PID_REAPED)))
{
debug_printf ("looping because pid %d, procinfo->pid %d, "
"procinfo->dwProcessid %u has PID_EXITED|PID_REAPED set",
@@ -381,15 +430,8 @@ pinfo::init (pid_t n, DWORD flag, HANDLE h0)
if (flag & PID_NEW)
procinfo->start_time = time (NULL);
- if (!created)
- /* nothing */;
- else if (!(flag & PID_EXECED))
+ if (created)
procinfo->pid = n;
- else
- {
- procinfo->process_state |= PID_IN_USE | PID_EXECED;
- procinfo->pid = myself->pid;
- }
h = h0; /* Success! */
break;
@@ -529,7 +571,7 @@ _pinfo::set_ctty (fhandler_termios *fh, int flags)
bool __reg1
_pinfo::exists ()
{
- return process_state && !(process_state & (PID_EXITED | PID_REAPED | PID_EXECED));
+ return process_state && !(process_state & (PID_EXITED | PID_REAPED));
}
bool
@@ -1279,6 +1321,8 @@ void
pinfo::release ()
{
_pinfo_release ();
+ if (winpid_hdl)
+ NtClose (winpid_hdl);
HANDLE close_h;
if (rd_proc_pipe)
{
@@ -1389,7 +1433,7 @@ winpids::add (DWORD& nelem, bool winpid, DWORD pid)
make a copy of the shared memory area when it exists (it may not). */
perform_copy = onreturn ? make_copy : true;
- p.init (cygpid, PID_NOREDIR | pinfo_access, NULL);
+ p.init (cygpid, PID_PROCINFO | pinfo_access, NULL);
}
/* If we're just looking for winpids then don't do any special cygwin "stuff* */
@@ -1403,9 +1447,9 @@ winpids::add (DWORD& nelem, bool winpid, DWORD pid)
that it isn't a cygwin process. */
if (!p)
{
- if (!pinfo_access)
+ if (!pinfo_access || !cygpid)
return;
- p.init (cygpid, PID_NOREDIR, NULL);
+ p.init (cygpid, PID_PROCINFO, NULL);
if (!p)
return;
}
@@ -1491,7 +1535,7 @@ winpids::enum_processes (bool winpid)
{
restart = FALSE;
f.dbi.ObjectName.Buffer[f.dbi.ObjectName.Length / sizeof (WCHAR)] = L'\0';
- if (wcsncmp (f.dbi.ObjectName.Buffer, L"cygpid.", 7) == 0)
+ if (wcsncmp (f.dbi.ObjectName.Buffer, L"winpid.", 7) == 0)
{
DWORD pid = wcstoul (f.dbi.ObjectName.Buffer + 7, NULL, 10);
add (nelem, false, pid);
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index c4881c7..81e10d3 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -53,8 +53,6 @@ public:
DWORD exitcode; /* set when process exits */
-#define PINFO_REDIR_SIZE ((char *) &myself.procinfo->exitcode - (char *) myself.procinfo)
-
/* > 0 if started by a cygwin process */
DWORD cygstarted;
@@ -147,22 +145,25 @@ public:
class pinfo: public pinfo_minimal
{
bool destroy;
+ HANDLE winpid_hdl;
_pinfo *procinfo;
public:
bool waiter_ready;
class cygthread *wait_thread;
void __reg3 init (pid_t, DWORD, HANDLE);
- pinfo (_pinfo *x = NULL): pinfo_minimal (), destroy (false), procinfo (x),
- waiter_ready (false), wait_thread (NULL) {}
- pinfo (pid_t n, DWORD flag = 0): pinfo_minimal (), destroy (false),
- procinfo (NULL), waiter_ready (false),
- wait_thread (NULL)
+ pinfo (_pinfo *x = NULL)
+ : pinfo_minimal (), destroy (false), winpid_hdl (NULL), procinfo (x),
+ waiter_ready (false), wait_thread (NULL) {}
+ pinfo (pid_t n, DWORD flag = 0)
+ : pinfo_minimal (), destroy (false), winpid_hdl (NULL), procinfo (NULL),
+ waiter_ready (false), wait_thread (NULL)
{
init (n, flag, NULL);
}
pinfo (HANDLE, pinfo_minimal&, pid_t);
void __reg2 thisproc (HANDLE);
+ void create_winpid_symlink (pid_t, DWORD);
inline void _pinfo_release ();
void release ();
bool __reg1 wait ();
@@ -239,11 +240,8 @@ public:
void release ();
};
-extern __inline pid_t
-cygwin_pid (pid_t pid)
-{
- return pid;
-}
+pid_t create_cygwin_pid ();
+pid_t cygwin_pid (DWORD);
void __stdcall pinfo_init (char **, int);
extern pinfo myself;
diff --git a/winsup/cygwin/release/3.0 b/winsup/cygwin/release/3.0
index f4433c3..907405a 100644
--- a/winsup/cygwin/release/3.0
+++ b/winsup/cygwin/release/3.0
@@ -61,6 +61,9 @@ What changed:
- Kerberos/MSV1_0 S4U authentication replaces two old methods:
Creating a token from scratch and Cygwin LSA authentication package.
+- Cygwin PIDs have been decoupled from Windows PID. Cygwin PIDs are
+ now incrementally dealt in the range from 2 up to 65535, POSIX-like.
+
Bug Fixes
---------
diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc
index dd16f14..e87f2f9 100644
--- a/winsup/cygwin/shared.cc
+++ b/winsup/cygwin/shared.cc
@@ -323,12 +323,17 @@ shared_info::initialize ()
spinlock sversion (version, CURR_SHARED_MAGIC);
if (!sversion)
{
+ LUID luid;
+
cb = sizeof (*this);
get_session_parent_dir (); /* Create session dir if first process. */
init_obcaseinsensitive (); /* Initialize obcaseinsensitive */
tty.init (); /* Initialize tty table */
mt.initialize (); /* Initialize shared tape information */
loadavg.initialize (); /* Initialize loadavg information */
+ NtAllocateLocallyUniqueId (&luid);/* Initialize pid_src to a low */
+ InterlockedExchange (&pid_src, /* random value to make start pid */
+ luid.LowPart % 2048);/* less predictably */
/* Defer debug output printing the installation root and installation key
up to this point. Debug output except for system_printf requires
the global shared memory to exist. */
diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h
index f331a3a..1a5648b 100644
--- a/winsup/cygwin/shared_info.h
+++ b/winsup/cygwin/shared_info.h
@@ -33,7 +33,7 @@ public:
/* Data accessible to all tasks */
-#define CURR_SHARED_MAGIC 0x9b1c0f25U
+#define CURR_SHARED_MAGIC 0x6758de88U
#define USER_VERSION 1
@@ -50,6 +50,7 @@ class shared_info
DWORD obcaseinsensitive;
mtinfo mt;
loadavginfo loadavg;
+ LONG pid_src;
void initialize ();
void init_obcaseinsensitive ();
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 37db526..58e2696 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -709,7 +709,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
::cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
if (mode != _P_OVERLAY)
- cygpid = cygwin_pid (pi.dwProcessId);
+ cygpid = create_cygwin_pid ();
else
cygpid = myself->pid;