diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index ad775bc3b..fa7cb3ef1 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,32 @@ +2005-10-17 Christopher Faylor + + Change process_lock to lock_process throughout. + Change all calls to new cygthread to handle extra argument, throughout. + * cygthread.h (cygthread::callproc): Declare new method. + (cygthread::cygthread): Add optional length argument to allow copying + arguments to executing thread. + * cygthread.cc (cygthread::callproc): Define new method. + (cygthread::stub): Use callfunc to invoke thread func to allow + potentially allocating stack memory which will be returned. + (cygthread::simplestub): Ditto. + (cygthread::cygthread): Accept arglen argument. Reset ev here prior to + activating thread. Wait for ev after activating thread if we're + copying contents to the thread. Wait until the end before setting h, + to allow thread synchronization. + (cygthread::release): Don't reset ev here. Rely on that happening the next + time the thread is activated. + * pinfo.h (commune_process): Rename declaration from _pinfo::commune_process. + * pinfo.cc (commune_process): Ditto for definition. Modify slightly to allow + running as a separate cygthread. + * sigproc.cc (child_info::sync): Always wait for both subproc_ready and + any hProcess if we have a cygwin parent. + (talktome): Change argument to be a pointer to siginfo_t. Contiguously + allocate whole siginfo_t structure + any needed extra for eventual passing + to commune_process thread. + (wait_sig): Accommodate change in talktome argument. + + * pipe.cc (fhandler_pipe::fixup_after_exec): Remove debugging. + 2005-10-17 Corinna Vinschen * autoload.cc: Never load wsock32.dll. Load all wsock32 function diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h index dc6a72457..d3c372c7d 100644 --- a/winsup/cygwin/child_info.h +++ b/winsup/cygwin/child_info.h @@ -54,7 +54,7 @@ public: child_info (): subproc_ready (NULL), parent (NULL) {} ~child_info (); void ready (bool); - bool sync (int, HANDLE, DWORD) __attribute__ ((regparm (3))); + bool sync (int, HANDLE&, DWORD) __attribute__ ((regparm (3))); }; class mount_info; diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 059e01d2e..d9301d415 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -415,11 +415,11 @@ class cygheap_fdenum : public cygheap_fdmanip } }; -class process_lock +class lock_process { bool skip_unlock; public: - process_lock (bool exiting = false) + lock_process (bool exiting = false) { cygheap->fdtab.lock (); skip_unlock = exiting; @@ -429,7 +429,7 @@ public: muto::set_exiting_thread (); } } - ~process_lock () + ~lock_process () { if (!skip_unlock) cygheap->fdtab.unlock (); diff --git a/winsup/cygwin/cygthread.cc b/winsup/cygwin/cygthread.cc index 385995382..09eabed54 100644 --- a/winsup/cygwin/cygthread.cc +++ b/winsup/cygwin/cygthread.cc @@ -25,6 +25,36 @@ static cygthread NO_COPY threads[32]; DWORD NO_COPY cygthread::main_thread_id; bool NO_COPY cygthread::exiting; +void +cygthread::callfunc (bool issimplestub) +{ + void *pass_arg; + if (arg == cygself) + pass_arg = this; + else if (!arglen) + pass_arg = arg; + else + { + if (issimplestub) + ev = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); + pass_arg = alloca (arglen); + memcpy (pass_arg, arg, arglen); + SetEvent (ev); + } + if (issimplestub) + { + /* Wait for main thread to assign 'h' */ + while (!h) + low_priority_sleep (0); + if (ev) + CloseHandle (ev); + ev = h; + } + /* Cygwin threads should not call ExitThread directly */ + func (pass_arg); + /* ...so the above should always return */ +} + /* Initial stub called by cygthread constructor. Performs initial per-thread initialization and loops waiting for another thread function to execute. */ @@ -69,9 +99,7 @@ cygthread::stub (VOID *arg) return 0; } - /* Cygwin threads should not call ExitThread directly */ - info->func (info->arg == cygself ? info : info->arg); - /* ...so the above should always return */ + info->callfunc (false); HANDLE notify = info->notify_detached; /* If func is NULL, the above function has set that to indicate @@ -111,11 +139,7 @@ cygthread::simplestub (VOID *arg) cygthread *info = (cygthread *) arg; _my_tls._ctinfo = info; info->stack_ptr = &arg; - /* Wait for main thread to assign 'h' */ - while (!info->h) - low_priority_sleep (0); - info->ev = info->h; - info->func (info->arg == cygself ? info : info->arg); + info->callfunc (true); return 0; } @@ -165,30 +189,43 @@ out: return info; } -cygthread::cygthread (LPTHREAD_START_ROUTINE start, LPVOID param, +cygthread::cygthread (LPTHREAD_START_ROUTINE start, size_t n, void *param, const char *name, HANDLE notify) - : __name (name), func (start), arg (param), notify_detached (notify) + : __name (name), func (start), arglen (n), arg (param), notify_detached (notify) { thread_printf ("name %s, id %p", name, id); + HANDLE htobe; if (h) { + if (ev) + ResetEvent (ev); while (!thread_sync) low_priority_sleep (0); SetEvent (thread_sync); thread_printf ("activated name '%s', thread_sync %p for thread %p", name, thread_sync, id); + htobe = h; } else { stack_ptr = NULL; - h = CreateThread (&sec_none_nih, 0, is_freerange ? simplestub : stub, - this, 0, &id); - if (!h) + htobe = CreateThread (&sec_none_nih, 0, is_freerange ? simplestub : stub, + this, 0, &id); + if (!htobe) api_fatal ("CreateThread failed for %s - %p<%p>, %E", name, h, id); thread_printf ("created name '%s', thread %p, id %p", name, h, id); #ifdef DEBUGGING terminated = false; #endif } + + if (n) + { + while (!ev) + low_priority_sleep (0); + WaitForSingleObject (ev, INFINITE); + ResetEvent (ev); + } + h = htobe; } /* Return the symbolic name of the current thread for debugging. @@ -238,8 +275,6 @@ cygthread::release (bool nuke_h) #endif __name = NULL; func = NULL; - if (ev) - ResetEvent (ev); if (!InterlockedExchange (&inuse, 0)) #ifdef DEBUGGING api_fatal ("released a thread that was not inuse"); diff --git a/winsup/cygwin/cygthread.h b/winsup/cygwin/cygthread.h index 9da8d1c52..da7172e63 100644 --- a/winsup/cygwin/cygthread.h +++ b/winsup/cygwin/cygthread.h @@ -23,6 +23,7 @@ class cygthread bool terminated; #endif LPTHREAD_START_ROUTINE func; + unsigned arglen; VOID *arg; bool is_freerange; static bool exiting; @@ -33,9 +34,10 @@ class cygthread static DWORD WINAPI simplestub (VOID *); static DWORD main_thread_id; static const char * name (DWORD = 0); + void callfunc (bool) __attribute__ ((noinline, regparm (2))); void auto_release () {func = NULL;} void release (bool); - cygthread (LPTHREAD_START_ROUTINE, LPVOID, const char *, HANDLE = NULL); + cygthread (LPTHREAD_START_ROUTINE, unsigned, LPVOID, const char *, HANDLE = NULL); cygthread () {}; static void init (); bool detach (HANDLE = NULL); diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 6f82e1273..03df872c0 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -1021,7 +1021,7 @@ do_exit (int status) } #endif - process_lock until_exit (true); + lock_process until_exit (true); if (exit_state < ES_GLOBAL_DTORS) { diff --git a/winsup/cygwin/dtable.h b/winsup/cygwin/dtable.h index b71b3f1db..e34a3ecf4 100644 --- a/winsup/cygwin/dtable.h +++ b/winsup/cygwin/dtable.h @@ -89,7 +89,7 @@ public: friend class cygheap_fdget; friend class cygheap_fdnew; friend class cygheap_fdenum; - friend class process_lock; + friend class lock_process; }; fhandler_base *build_fh_dev (const device&, const char * = NULL); diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index b1315239d..be8fb41d2 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1183,7 +1183,7 @@ signal_exit (int rc) TerminateProcess (hExeced, sigExeced = rc); } - process_lock until_exit (true); + lock_process until_exit (true); if (hExeced || exit_state) myself.exit (rc); diff --git a/winsup/cygwin/fhandler_netdrive.cc b/winsup/cygwin/fhandler_netdrive.cc index 4665d2893..4bc8ec3e2 100644 --- a/winsup/cygwin/fhandler_netdrive.cc +++ b/winsup/cygwin/fhandler_netdrive.cc @@ -95,7 +95,7 @@ create_thread_and_wait (int what, PVOID in, PVOID out, DWORD outsize, { netdriveinf ndi = { what, 0, in, out, outsize, CreateSemaphore (&sec_none_nih, 0, 2, NULL) }; - cygthread *thr = new cygthread (thread_netdrive, (LPVOID) &ndi, name); + cygthread *thr = new cygthread (thread_netdrive, 0, &ndi, name); if (thr->detach (ndi.sem)) ndi.ret = ERROR_OPERATION_ABORTED; CloseHandle (ndi.sem); diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 5016c5a4f..630caedca 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -81,15 +81,15 @@ fhandler_tty_master::init () set_close_on_exec (true); cygthread *h; - h = new cygthread (process_input, cygself, "ttyin"); + h = new cygthread (process_input, 0, cygself, "ttyin"); h->SetThreadPriority (THREAD_PRIORITY_HIGHEST); h->zap_h (); - h = new cygthread (process_ioctl, cygself, "ttyioctl"); + h = new cygthread (process_ioctl, 0, cygself, "ttyioctl"); h->SetThreadPriority (THREAD_PRIORITY_HIGHEST); h->zap_h (); - h = new cygthread (process_output, cygself, "ttyout"); + h = new cygthread (process_output, 0, cygself, "ttyout"); h->SetThreadPriority (THREAD_PRIORITY_HIGHEST); h->zap_h (); diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 5df86c730..26d910cfe 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -139,8 +139,9 @@ pinfo::zap_cwd () void pinfo::exit (DWORD n) { - process_lock until_exit (); + lock_process until_exit (); cygthread::terminate (); + if (n != EXITCODE_NOSET) self->exitcode = EXITCODE_SET | n;/* We're really exiting. Record the UNIX exit code. */ else @@ -378,9 +379,10 @@ _pinfo::alive () extern char **__argv; -void -_pinfo::commune_process (siginfo_t& si) +DWORD WINAPI +commune_process (void *arg) { + siginfo_t& si = *((siginfo_t *) arg); char path[CYG_MAX_PATH]; DWORD nr; HANDLE& tothem = si._si_commune._si_write_handle; @@ -389,7 +391,7 @@ _pinfo::commune_process (siginfo_t& si) if (process_sync) // FIXME: this test shouldn't be necessary ProtectHandle (process_sync); - process_lock now (false); + lock_process now (false); switch (si._si_commune._si_code) { @@ -546,6 +548,8 @@ _pinfo::commune_process (siginfo_t& si) ForceCloseHandle (process_sync); } CloseHandle (tothem); + _my_tls._ctinfo->auto_release (); + return 0; } commune_result @@ -587,7 +591,7 @@ _pinfo::commune_request (__uint32_t code, ...) break; } - process_lock now (); + lock_process now (); locked = true; char name_buf[CYG_MAX_PATH]; request_sync = CreateSemaphore (&sec_none_nih, 0, LONG_MAX, @@ -959,7 +963,7 @@ pinfo::wait () waiter_ready = false; /* Fire up a new thread to track the subprocess */ - cygthread *h = new cygthread (proc_waiter, this, "proc_waiter"); + cygthread *h = new cygthread (proc_waiter, 0, this, "proc_waiter"); if (!h) sigproc_printf ("tracking thread creation failed for pid %d", (*this)->pid); else diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h index 0c7a26413..2038f9b6e 100644 --- a/winsup/cygwin/pinfo.h +++ b/winsup/cygwin/pinfo.h @@ -105,7 +105,6 @@ public: sig_mask = mask; } - void commune_process (siginfo_t&); commune_result commune_request (__uint32_t, ...); bool alive (); fhandler_pipe *pipe_fhandler (HANDLE, size_t &); @@ -135,6 +134,8 @@ public: friend class pinfo; }; +DWORD WINAPI commune_process (void *); + enum parent_alerter { __ALERT_REPARENT = 111, // arbitrary non-signal value diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc index 3407f0945..8d16b1742 100644 --- a/winsup/cygwin/pipe.cc +++ b/winsup/cygwin/pipe.cc @@ -181,7 +181,7 @@ fhandler_pipe::read (void *in_ptr, size_t& in_len) else { pipeargs pi = {dynamic_cast(this), in_ptr, &in_len}; - cygthread *th = new cygthread (read_pipe, &pi, "read_pipe"); + cygthread *th = new cygthread (read_pipe, 0, &pi, "read_pipe"); if (th->detach (read_state) && !in_len) in_len = (size_t) -1; /* received a signal */ } @@ -236,7 +236,6 @@ fhandler_pipe::fixup_after_exec () void fhandler_pipe::fixup_after_fork (HANDLE parent) { -debug_printf ("here"); fhandler_base::fixup_after_fork (parent); if (guard) fork_fixup (parent, guard, "guard"); diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 4c93dd32d..1350a2b03 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -662,7 +662,7 @@ start_thread_pipe (select_record *me, select_stuff *stuff) pipeinf *pi = new pipeinf; pi->start = &stuff->start; pi->stop_thread_pipe = false; - pi->thread = new cygthread (thread_pipe, (LPVOID) pi, "select_pipe"); + pi->thread = new cygthread (thread_pipe, 0, pi, "select_pipe"); me->h = *pi->thread; if (!me->h) return 0; @@ -1091,7 +1091,7 @@ start_thread_serial (select_record *me, select_stuff *stuff) serialinf *si = new serialinf; si->start = &stuff->start; si->stop_thread_serial = false; - si->thread = new cygthread (thread_serial, (LPVOID) si, "select_serial"); + si->thread = new cygthread (thread_serial, 0, si, "select_serial"); me->h = *si->thread; stuff->device_specific_serial = (void *) si; return 1; @@ -1422,7 +1422,7 @@ start_thread_socket (select_record *me, select_stuff *stuff) stuff->device_specific_socket = (void *) si; si->start = &stuff->start; select_printf ("stuff_start %p", &stuff->start); - si->thread = new cygthread (thread_socket, (LPVOID) si, "select_socket"); + si->thread = new cygthread (thread_socket, 0, si, "select_socket"); me->h = *si->thread; return 1; @@ -1674,7 +1674,7 @@ start_thread_mailslot (select_record *me, select_stuff *stuff) mailslotinf *mi = new mailslotinf; mi->start = &stuff->start; mi->stop_thread_mailslot = false; - mi->thread = new cygthread (thread_mailslot, (LPVOID) mi, "select_mailslot"); + mi->thread = new cygthread (thread_mailslot, 0, mi, "select_mailslot"); me->h = *mi->thread; if (!me->h) return 0; diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 27f38f0ae..3a5132600 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -481,7 +481,7 @@ sigproc_init () sync_proc_subproc.init ("sync_proc_subproc"); my_sendsig = INVALID_HANDLE_VALUE; // changed later - cygthread *hwait_sig = new cygthread (wait_sig, cygself, "sig"); + cygthread *hwait_sig = new cygthread (wait_sig, 0, cygself, "sig"); hwait_sig->zap_h (); global_sigs[SIGSTOP].sa_flags = SA_RESTART | SA_NODEFER; @@ -816,36 +816,44 @@ child_info::ready (bool execed) } bool -child_info::sync (pid_t pid, HANDLE hProcess, DWORD howlong) +child_info::sync (pid_t pid, HANDLE& hProcess, DWORD howlong) { - if (!subproc_ready) - { - sigproc_printf ("not waiting. subproc_ready is NULL"); - return false; - } - - HANDLE w4[2]; - w4[0] = subproc_ready; - w4[1] = hProcess; - bool res; - sigproc_printf ("waiting for subproc_ready(%p) and child process(%p)", w4[0], w4[1]); - switch (WaitForMultipleObjects (2, w4, FALSE, howlong)) + if (!subproc_ready && !myself->wr_proc_pipe) + res = false; + else { - case WAIT_OBJECT_0: - sigproc_printf ("got subproc_ready for pid %d", pid); - res = true; - break; - case WAIT_OBJECT_0 + 1: - sigproc_printf ("process exited before subproc_ready"); - if (WaitForSingleObject (subproc_ready, 0) == WAIT_OBJECT_0) - sigproc_printf ("should never happen. noticed subproc_ready after process exit"); - res = false; - break; - default: - system_printf ("wait failed, pid %d, %E", pid); - res = false; - break; + HANDLE w4[2]; + unsigned n = 0; + unsigned nsubproc_ready; + + if (!subproc_ready) + nsubproc_ready = WAIT_OBJECT_0 + 3; + else + { + w4[n++] = subproc_ready; + nsubproc_ready = 0; + } + w4[n++] = hProcess; + + sigproc_printf ("waiting for subproc_ready(%p) and child process(%p)", w4[0], w4[1]); + DWORD x = WaitForMultipleObjects (n, w4, FALSE, howlong); + x -= WAIT_OBJECT_0; + if (x >= n) + { + system_printf ("wait failed, pid %d, %E", pid); + res = false; + } + else + { + if (n == nsubproc_ready) + { + CloseHandle (hProcess); + hProcess = NULL; + } + sigproc_printf ("process %d synchronized, WFMO returned %d", pid, x); + res = true; + } } return res; } @@ -968,25 +976,28 @@ stopped_or_terminated (waitq *parent_w, _pinfo *child) } static void -talktome (siginfo_t& si, HANDLE readsig) +talktome (siginfo_t *si, HANDLE readsig) { - sigproc_printf ("pid %d wants some information", si.si_pid); - pinfo pi (si.si_pid); - sigproc_printf ("pid %d pi %p", si.si_pid, (_pinfo *) pi); // DELETEME - if (si._si_commune._si_code & PICOM_EXTRASTR) + unsigned size = sizeof (*si); + sigproc_printf ("pid %d wants some information", si->si_pid); + if (si->_si_commune._si_code & PICOM_EXTRASTR) { size_t n; DWORD nb; if (!ReadFile (readsig, &n, sizeof (n), &nb, NULL) || nb != sizeof (n)) return; - // FIXME: Is alloca here? - si._si_commune._si_str = (char *) alloca (n + 1); - if (!ReadFile (readsig, si._si_commune._si_str, n, &nb, NULL) || nb != n) + siginfo_t *newsi = (siginfo_t *) alloca (size += n + 1); + *newsi = *si; + newsi->_si_commune._si_str = (char *) (newsi + 1); + if (!ReadFile (readsig, newsi->_si_commune._si_str, n, &nb, NULL) || nb != n) return; - si._si_commune._si_str[n] = '\0'; + newsi->_si_commune._si_str[n] = '\0'; + si = newsi; } + + pinfo pi (si->si_pid); if (pi) - pi->commune_process (si); + new cygthread (commune_process, size, si, "commune_process"); } void @@ -1100,7 +1111,7 @@ wait_sig (VOID *) switch (pack.si.si_signo) { case __SIGCOMMUNE: - talktome (pack.si, readsig); + talktome (&pack.si, readsig); break; case __SIGSTRACE: strace.hello (); diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index df13d3b1b..17c7e5828 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -814,11 +814,7 @@ spawn_guts (const char * prog_arg, const char *const *argv, switch (mode) { case _P_OVERLAY: - if (!synced) - /* let myself.exit handle this */; - else if (myself->wr_proc_pipe) - myself.hProcess = NULL; - else + if (!synced && !myself->wr_proc_pipe) { extern bool is_toplevel_proc; is_toplevel_proc = true; diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/timer.cc index 552e56f6e..c6dc2754b 100644 --- a/winsup/cygwin/timer.cc +++ b/winsup/cygwin/timer.cc @@ -245,7 +245,7 @@ timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalu syncthread = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); else ResetEvent (syncthread); - new cygthread (timer_thread, this, "itimer", syncthread); + new cygthread (timer_thread, 0, this, "itimer", syncthread); } return 0; diff --git a/winsup/cygwin/window.cc b/winsup/cygwin/window.cc index 1d9b4af84..0821c64f8 100644 --- a/winsup/cygwin/window.cc +++ b/winsup/cygwin/window.cc @@ -118,7 +118,7 @@ HWND () if (!hwnd) { _lock.upforgrabs (); - cygthread *h = new cygthread (::winthread, this, "win"); + cygthread *h = new cygthread (::winthread, 0, this, "win"); h->SetThreadPriority (THREAD_PRIORITY_HIGHEST); h->zap_h (); lock ();