diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 24500a1ce..f953401be 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,8 +1,35 @@ +Wed May 17 01:05:52 2000 Christopher Faylor + + * path.cc (mount_info::cygdrive_posix_path): Don't add trailing slash + if referring to something like c:\. + * dcrt0.cc (dll_crt0_1): Move uinfo initialization prior to sig_send + initialization to give signal thread a chance to finish. + * debug.cc (WFSO): Move to sigproc.cc + (WFMO): Ditto. + * exceptions.cc (interruptible): Allocate slightly more space for + directory just for paranoia's sake. + (call_handler): Eliminate nonmain argument. Determine if main thread + has set a frame pointer and use it if so. + (sig_handle): Eliminate nonmain argument. + * net.cc: Record frame information in appropriate routines throughout. + * select.cc (select): Ditto. + * sigproc.cc: Use sigthread structure to record mainthread id + throughout. + (sig_send): Record frame information for signal handler. + (wait_sig): Reflect argument change in sig_handle. + (WFSO): Move here and record frame information for signal handler. + (WFMO): Ditto. + * sigproc.h: Implement new "sigthread" class. Implement "sigframe" + class for manipulating signal frame info. + * thread.cc (__pthread_kill): Use standard _kill() function rather than + calling sig_send directly. + * winsup.h: Eliminate ebp element from signal_dispatch class. + Tue May 16 23:39:00 2000 Corinna Vinschen Patch suggested by John Rowley * fhandler_tape.cc (fhandler_dev_tape::ioctl): Check - for filemark feature on MTWEOF operation. + for filemark feature on MTWEOF operation. Tue May 16 11:49:13 2000 Christopher Faylor diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index a04709ab0..9810fd000 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -746,15 +746,15 @@ dll_crt0_1 () set_errno (0); debug_printf ("user_data->main %p", user_data->main); + /* Initialize uid, gid. */ + uinfo_init (); + /* Flush signals and ensure that signal thread is up and running. Can't do this for noncygwin case since the signal thread is blocked due to LoadLibrary serialization. */ if (!dynamically_loaded) sig_send (NULL, __SIGFLUSH); - /* Initialize uid, gid. */ - uinfo_init (); - if (user_data->main && !dynamically_loaded) exit (user_data->main (argc, argv, *user_data->envptr)); } diff --git a/winsup/cygwin/debug.cc b/winsup/cygwin/debug.cc index 255d0aed0..ecc689d8f 100644 --- a/winsup/cygwin/debug.cc +++ b/winsup/cygwin/debug.cc @@ -9,7 +9,6 @@ details. */ #define NO_DEBUG_DEFINES #include "winsup.h" #include "exceptions.h" -#include "sync.h" static muto NO_COPY *threadname_lock = NULL; #define lock_threadname() \ @@ -52,7 +51,7 @@ int __stdcall iscygthread() { DWORD tid = GetCurrentThreadId (); - if (tid != maintid) + if (tid != mainthread.id) for (DWORD i = 0; i < NTHREADS && threads[i].name != NULL; i++) if (threads[i].id == tid) return 1; @@ -302,27 +301,3 @@ close_handle (const char *func, int ln, HANDLE h, const char *name, BOOL force) return ret; } #endif /*DEBUGGING*/ - -extern "C" { -/* Provide a stack frame when calling WaitFor* functions */ - -#undef WaitForSingleObject - -DWORD __stdcall -WFSO (HANDLE hHandle, DWORD dwMilliseconds) -{ - DWORD ret; - ret = WaitForSingleObject (hHandle, dwMilliseconds); - return ret; -} - -#undef WaitForMultipleObjects - -DWORD __stdcall -WFMO (DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds) -{ - DWORD ret; - ret = WaitForMultipleObjects (nCount, lpHandles, fWaitAll, dwMilliseconds); - return ret; -} -} diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 4720d8e6e..b9e58a209 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -18,7 +18,6 @@ details. */ #define DECLSPEC_IMPORT #include #include "autoload.h" -#include "sync.h" char debugger_command[2 * MAX_PATH + 20]; @@ -566,7 +565,8 @@ interruptible (DWORD pc) if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m)) sigproc_printf ("couldn't get memory info, %E"); - char *checkdir = (char *) alloca (windows_system_directory_length + 2); + char *checkdir = (char *) alloca (windows_system_directory_length + 4); + memset (checkdir, 0, sizeof (checkdir)); # define h ((HMODULE) m.AllocationBase) if (h == user_data->hmodule) res = 1; @@ -597,7 +597,6 @@ interrupt_setup (int sig, struct sigaction& siga, void *handler, sigsave.func = (void (*)(int)) handler; sigsave.sig = sig; sigsave.saved_errno = -1; // Flag: no errno to save - sigsave.ebp = 0; } static void @@ -656,18 +655,33 @@ set_sig_errno (int e) } static int -call_handler (int sig, struct sigaction& siga, void *handler, int nonmain) +call_handler (int sig, struct sigaction& siga, void *handler) { CONTEXT cx; - DWORD ebp; int interrupted = 1; HANDLE hth = NULL; + DWORD ebp; int res; + int locked; - if (!nonmain) - ebp = sigsave.ebp; + if (!mainthread.lock) + locked = 0; else { + mainthread.lock->acquire (); + locked = 1; + } + + if (mainthread.frame) + ebp = mainthread.frame; + else + { + if (locked) + { + mainthread.lock->release (); + locked = 0; + } + hth = myself->getthread2signal (); /* Suspend the thread which will receive the signal. But first ensure that this thread doesn't have the sync_proc_subproc and mask_sync mutos, since @@ -682,9 +696,15 @@ call_handler (int sig, struct sigaction& siga, void *handler, int nonmain) muto *m; /* FIXME: Make multi-thread aware */ for (m = muto_start.next; m != NULL; m = m->next) - if (m->unstable () || m->owner () == maintid) + if (m->unstable () || m->owner () == mainthread.id) goto keep_looping; + if (mainthread.frame) + { + ebp = mainthread.frame; /* try to avoid a race */ + goto ebp_set; + } + break; keep_looping: @@ -707,7 +727,8 @@ call_handler (int sig, struct sigaction& siga, void *handler, int nonmain) ebp = cx.Ebp; } - if (hExeced != NULL || (nonmain && interruptible (cx.Eip))) +ebp_set: + if (hExeced != NULL || (!mainthread.frame && interruptible (cx.Eip))) interrupt_now (&cx, sig, siga, handler); else if (!interrupt_on_return (ebp, sig, siga, handler)) { @@ -734,6 +755,9 @@ out: sigproc_printf ("ResumeThread returned %d", res); } + if (locked) + mainthread.lock->release (); + sigproc_printf ("returning %d", interrupted); return interrupted; } @@ -835,7 +859,7 @@ sig_handle_tty_stop (int sig) } int __stdcall -sig_handle (int sig, int nonmain) +sig_handle (int sig) { int rc = 0; @@ -914,7 +938,7 @@ stop: dosig: /* Dispatch to the appropriate function. */ sigproc_printf ("signal %d, about to call %p", sig, thissig.sa_handler); - rc = call_handler (sig, thissig, handler, nonmain); + rc = call_handler (sig, thissig, handler); done: sigproc_printf ("returning %d", rc); diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc index 7e17fd9ec..22aa207b4 100644 --- a/winsup/cygwin/malloc_wrapper.cc +++ b/winsup/cygwin/malloc_wrapper.cc @@ -13,7 +13,6 @@ details. */ #include "winsup.h" #include -#include "sync.h" /* we provide these stubs to call into a user's provided malloc if there is one - otherwise diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index bfe4b6554..8e3f9f4de 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -421,6 +421,7 @@ cygwin_sendto (int fd, { fhandler_socket *h = (fhandler_socket *) dtable[fd]; sockaddr_in sin; + sigframe thisframe (mainthread, 0); if (get_inet_addr (to, tolen, &sin, &tolen) == 0) return -1; @@ -446,6 +447,7 @@ cygwin_recvfrom (int fd, int *fromlen) { fhandler_socket *h = (fhandler_socket *) dtable[fd]; + sigframe thisframe (mainthread, 0); debug_printf ("recvfrom %d", h->get_socket ()); @@ -602,6 +604,7 @@ cygwin_connect (int fd, int res; fhandler_socket *sock = get (fd); sockaddr_in sin; + sigframe thisframe (mainthread, 0); if (get_inet_addr (name, namelen, &sin, &namelen) == 0) return -1; @@ -714,6 +717,7 @@ int cygwin_accept (int fd, struct sockaddr *peer, int *len) { int res = -1; + sigframe thisframe (mainthread, 0); fhandler_socket *sock = get (fd); if (sock) @@ -899,7 +903,7 @@ int cygwin_shutdown (int fd, int how) { int res = -1; - + sigframe thisframe (mainthread, 0); fhandler_socket *sock = get (fd); if (sock) @@ -942,6 +946,7 @@ int cygwin_recv (int fd, void *buf, int len, unsigned int flags) { fhandler_socket *h = (fhandler_socket *) dtable[fd]; + sigframe thisframe (mainthread, 0); int res = recv (h->get_socket (), (char *) buf, len, flags); if (res == SOCKET_ERROR) @@ -967,6 +972,7 @@ int cygwin_send (int fd, const void *buf, int len, unsigned int flags) { fhandler_socket *h = (fhandler_socket *) dtable[fd]; + sigframe thisframe (mainthread, 0); int res = send (h->get_socket (), (const char *) buf, len, flags); if (res == SOCKET_ERROR) @@ -1353,6 +1359,7 @@ cygwin_rcmd (char **ahost, unsigned short inport, char *locuser, { int res = -1; SOCKET fd2s; + sigframe thisframe (mainthread, 0); int res_fd = dtable.find_unused_handle (); if (res_fd == -1) @@ -1392,6 +1399,7 @@ int cygwin_rresvport (int *port) { int res = -1; + sigframe thisframe (mainthread, 0); int res_fd = dtable.find_unused_handle (); if (res_fd == -1) @@ -1420,6 +1428,7 @@ cygwin_rexec (char **ahost, unsigned short inport, char *locuser, { int res = -1; SOCKET fd2s; + sigframe thisframe (mainthread, 0); int res_fd = dtable.find_unused_handle (); if (res_fd == -1) @@ -1597,6 +1606,7 @@ fhandler_socket::~fhandler_socket () int fhandler_socket::read (void *ptr, size_t len) { + sigframe thisframe (mainthread); int res = recv (get_socket (), (char *) ptr, len, 0); if (res == SOCKET_ERROR) { @@ -1608,6 +1618,7 @@ fhandler_socket::read (void *ptr, size_t len) int fhandler_socket::write (const void *ptr, size_t len) { + sigframe thisframe (mainthread); int res = send (get_socket (), (const char *) ptr, len, 0); if (res == SOCKET_ERROR) { @@ -1623,6 +1634,7 @@ int fhandler_socket::close () { int res = 0; + sigframe thisframe (mainthread); if (closesocket (get_socket ())) { @@ -1661,6 +1673,7 @@ fhandler_socket::ioctl (unsigned int cmd, void *p) int res; struct ifconf *ifc; struct ifreq *ifr; + sigframe thisframe (mainthread); switch (cmd) { diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 42170aa16..0251c9004 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1101,7 +1101,7 @@ mount_info::cygdrive_posix_path (const char *src, char *dst, int trailing_slash_ The cygdrive prefix always ends with a trailing slash so the drive letter is added after the path. */ dst[len++] = tolower (src[0]); - if (!src[2]) + if (!src[2] || (SLASH_P (src[2]) && !src[3])) dst[len++] = '\000'; else { @@ -1136,11 +1136,17 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, int keep_rel_p) { int src_path_len = strlen (src_path); - int trailing_slash_p = (src_path_len > 0 - && SLASH_P (src_path[src_path_len - 1])); - int relative_path_p = (! SLASH_P (*src_path) - && strchr (src_path, ':') == NULL); + int relative_path_p = !isabspath (src_path); + int trailing_slash_p; + if (src_path_len <= 1) + trailing_slash_p = 0; + else + { + const char *lastchar = src_path + src_path_len - 1; + trailing_slash_p = SLASH_P (*lastchar) && lastchar[-1] != ':'; + } + debug_printf ("conv_to_posix_path (%s, %s)", src_path, keep_rel_p ? "keep-rel" : "no-keep-rel"); MALLOC_CHECK; @@ -1212,8 +1218,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, caller must want an absolute path (otherwise we would have returned above). So we always return an absolute path at this point. */ if ((isalpha (pathbuf[0])) && (pathbuf[1] == ':')) - cygdrive_posix_path (pathbuf, posix_path, trailing_slash_p && - pathbuflen > 3); + cygdrive_posix_path (pathbuf, posix_path, trailing_slash_p); else { /* The use of src_path and not pathbuf here is intentional. diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 13df0febd..8d4b34c94 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -110,6 +110,7 @@ cygwin_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, fd_set *dummy_readfds = allocfd_set (n); fd_set *dummy_writefds = allocfd_set (n); fd_set *dummy_exceptfds = allocfd_set (n); + sigframe thisframe (mainthread, 0); #if 0 if (n > FD_SETSIZE) diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index a9f7c17ac..27541667d 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -16,7 +16,6 @@ details. */ #include #include #include "winsup.h" -#include "sync.h" extern BOOL allow_ntsec; @@ -101,7 +100,7 @@ Static waitq waitq_main; // Storage for main thread muto NO_COPY *sync_proc_subproc = NULL; // Control access to subproc stuff -DWORD NO_COPY maintid = 0; // ID of the main thread +sigthread NO_COPY mainthread; // ID of the main thread DWORD NO_COPY sigtid = 0; // ID of the signal thread int NO_COPY pending_signals = 0; // TRUE if signals pending @@ -605,7 +604,7 @@ sigproc_init () to a signal handler function. */ signal_arrived = CreateEvent(&sec_none_nih, TRUE, FALSE, NULL); - maintid = GetCurrentThreadId ();// For use in determining if signals + mainthread.id = GetCurrentThreadId ();// For use in determining if signals // should be blocked. if (!(hwait_sig = makethread (wait_sig, NULL, 0, "sig"))) @@ -719,10 +718,10 @@ sig_send (pinfo *p, int sig, DWORD ebp) HANDLE thiscatch = NULL; HANDLE thiscomplete = NULL; BOOL wait_for_completion; - extern signal_dispatch sigsave; + sigframe thisframe; if (p == myself_nowait_nonmain) - p = (tid == maintid) ? myself : myself_nowait; + p = (tid == mainthread.id) ? myself : myself_nowait; if (!(its_me = (p == NULL || p == myself || p == myself_nowait))) wait_for_completion = FALSE; else @@ -751,7 +750,7 @@ sig_send (pinfo *p, int sig, DWORD ebp) { if (!wait_for_completion) thiscatch = sigcatch_nosync; - else if (tid != maintid) + else if (tid != mainthread.id) { thiscatch = sigcatch_nonmain; thiscomplete = sigcomplete_nonmain; @@ -760,7 +759,7 @@ sig_send (pinfo *p, int sig, DWORD ebp) { thiscatch = sigcatch_main; thiscomplete = sigcomplete_main; - sigsave.ebp = ebp ?: (DWORD) __builtin_frame_address (1); + thisframe.set (mainthread); } } else if (!(thiscatch = getsem (p, "sigcatch", 0, 0))) @@ -1262,7 +1261,7 @@ wait_sig (VOID *) /* Signalled from a child process that it has stopped */ case __SIGCHILDSTOPPED: sip_printf ("Received child stopped notification"); - dispatched |= sig_handle (SIGCHLD, rc); + dispatched |= sig_handle (SIGCHLD); if (proc_subproc (PROC_CHILDSTOPPED, 0)) dispatched |= 1; break; @@ -1270,7 +1269,7 @@ wait_sig (VOID *) /* A normal UNIX signal */ default: sip_printf ("Got signal %d", sig); - int wasdispatched = sig_handle (sig, rc); + int wasdispatched = sig_handle (sig); dispatched |= wasdispatched; if (sig == SIGCHLD && wasdispatched) dispatched_sigchld = 1; @@ -1293,14 +1292,11 @@ wait_sig (VOID *) { case 0: SetEvent (sigcomplete_main); -sigproc_printf ("signalled sigcomplete_main %p", sigcomplete_main); break; case 1: ReleaseSemaphore (sigcomplete_nonmain, 1, NULL); -sigproc_printf ("signalled sigcomplete_nonmain %p", sigcomplete_nonmain); break; default: -sigproc_printf ("Did not signal anyone"); /* Signal from another process. No need to synchronize. */ break; } @@ -1367,3 +1363,29 @@ wait_subproc (VOID *) sip_printf ("done"); return 0; } + +extern "C" { +/* Provide a stack frame when calling WaitFor* functions */ + +#undef WaitForSingleObject + +DWORD __stdcall +WFSO (HANDLE hHandle, DWORD dwMilliseconds) +{ + DWORD ret; + sigframe thisframe (mainthread); + ret = WaitForSingleObject (hHandle, dwMilliseconds); + return ret; +} + +#undef WaitForMultipleObjects + +DWORD __stdcall +WFMO (DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds) +{ + DWORD ret; + sigframe thisframe (mainthread); + ret = WaitForMultipleObjects (nCount, lpHandles, fWaitAll, dwMilliseconds); + return ret; +} +} diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index 0ef9e74a1..eee35748f 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -32,12 +32,60 @@ typedef struct struct_waitq HANDLE thread_ev; } waitq; +class muto; + +struct sigthread +{ + DWORD id; + DWORD frame; + muto *lock; + sigthread () : id (0), frame (0), lock (0) {} +}; + +class sigframe +{ +private: + sigthread *st; + +public: + void set (sigthread &t, int up = 1) + { + if (!t.lock) + t.lock = new_muto (FALSE, "sigthread"); + t.lock->acquire (); + st = &t; + t.frame = (DWORD) (up ? __builtin_frame_address (1) : + __builtin_frame_address (0)); + t.lock->release (); + } + + sigframe () {st = NULL;} + sigframe (sigthread &t, int up = 1) + { + if (!t.frame || t.id == GetCurrentThreadId ()) + set (t, up); + else + st = NULL; + } + ~sigframe () + { + if (st) + { + st->lock->acquire (); + st->frame = 0; + st->lock->release (); + st = NULL; + } + } +}; + +extern sigthread mainthread; extern HANDLE signal_arrived; BOOL __stdcall my_parent_is_alive (); extern "C" int __stdcall sig_dispatch_pending (int force = FALSE) __asm__ ("sig_dispatch_pending"); extern "C" void __stdcall set_process_mask (sigset_t newmask); -int __stdcall sig_handle (int, int); +int __stdcall sig_handle (int); void __stdcall sig_clear (int); void __stdcall sig_set_pending (int); int __stdcall handle_sigsuspend (sigset_t); @@ -53,7 +101,6 @@ void __stdcall signal_fixup_after_fork (); extern char myself_nowait_dummy[]; extern char myself_nowait_nonmain_dummy[]; -extern DWORD maintid; extern HANDLE hExeced; // Process handle of new window // process created by spawn_guts() diff --git a/winsup/cygwin/sync.cc b/winsup/cygwin/sync.cc index 31bb27bdc..2ca3a27ac 100644 --- a/winsup/cygwin/sync.cc +++ b/winsup/cygwin/sync.cc @@ -20,12 +20,11 @@ details. */ #include #include #include "winsup.h" -#include "sync.h" muto NO_COPY muto_start; /* Constructor */ -muto::muto(int inh, const char *s) : sync (0), visits(0), waiters(-1), tid (0), next (NULL) +muto::muto (int inh, const char *s) : sync (0), visits(0), waiters(-1), tid (0), next (NULL) { /* Create event which is used in the fallback case when blocking is necessary */ if (!(bruteforce = CreateEvent (inh ? &sec_all_nih : &sec_none_nih, FALSE, FALSE, name))) diff --git a/winsup/cygwin/sync.h b/winsup/cygwin/sync.h index 138b767bb..9a6430ba9 100644 --- a/winsup/cygwin/sync.h +++ b/winsup/cygwin/sync.h @@ -47,7 +47,7 @@ extern muto muto_start; /* Use a statically allocated buffer as the storage for a muto */ #define new_muto(__inh, __name) \ ({ \ - static NO_COPY muto __mbuf; \ + static __attribute__((section(".data_cygwin_nocopy"))) muto __mbuf; \ (void) new ((char *) &__mbuf) muto (__inh, __name); \ __mbuf.next = muto_start.next; \ muto_start.next = &__mbuf; \ diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index c1d7071f2..5eaf301f3 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -184,6 +184,7 @@ static int read_handler (int fd, void *ptr, size_t len) { int res; + sigframe thisframe (mainthread); fhandler_base *fh = dtable[fd]; if (dtable.not_open (fd)) diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index b0d046897..ee18948de 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -705,7 +705,7 @@ __pthread_kill (pthread_t * thread, int sig) if (item->sigs) myself->setthread2signal (item); - int rval = sig_send (myself, sig); + int rval = _kill (myself->pid, sig); // unlock myself return rval; diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 76688a743..85fd41e29 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -85,6 +85,7 @@ extern HANDLE hMainProc; /* Now that pinfo has been defined, include... */ #include "debug.h" +#include "sync.h" #include "sigproc.h" #include "fhandler.h" #include "path.h" @@ -308,7 +309,6 @@ struct signal_dispatch void (*func) (int); int sig; int saved_errno; - DWORD ebp; DWORD oldmask; DWORD retaddr; DWORD *retaddr_on_stack;