* dcrt0.cc (init_windows_system_directory): Record system_wow64_directory

information.
* exceptions.cc (_cygtls::inside_kernel): Modernize comment.  Consider
executing a DLL from the Wow64 directory as being "in the kernel".
(_cygtls::call_signal_handler): For now, only deal with main_tls signals if
main_tls is known to be executing in the cygwin DLL.  To more closely emulate
linux, consider the operation to be restartable if not executing in the main
thread.
* globals.cc (windows_system_directory): Remove NO_COPY.
(windows_system_directory_length): Ditto.
(system_wow64_directory): New variable.
(system_wow64_directory_length): Ditto.
* select.cc (cygwin_select): Don't issue a EINTR on non-main threads since that
seems to be what Linux does.  Add missing break to signal case/switch.
(select_stuff::wait): Don't issue a EINTR on non-main threads since that seems
to be what Linux does.  Remove now-unneeded accommodation for
WAIT_IO_COMPLETION.  Add a comment.
* sigproc.h (cygwait): Ditto.  Don't return if signal_received noticed and it's
not the main thread.
* signal.cc (sigprocmask): Add standard syscall debug stuff.
* thread.cc (pthread_sigmask): Ditto.
This commit is contained in:
Christopher Faylor 2011-12-13 20:06:31 +00:00
parent 8d1bda71b4
commit 45d7b637fa
8 changed files with 95 additions and 43 deletions

View File

@ -1,3 +1,30 @@
2011-12-13 Christopher Faylor <me.cygwin2011@cgf.cx>
* dcrt0.cc (init_windows_system_directory): Record
system_wow64_directory information.
* exceptions.cc (_cygtls::inside_kernel): Modernize comment. Consider
executing a DLL from the Wow64 directory as being "in the kernel".
(_cygtls::call_signal_handler): For now, only deal with main_tls
signals if main_tls is known to be executing in the cygwin DLL. To
more closely emulate linux, consider the operation to be restartable if
not executing in the main thread.
* globals.cc (windows_system_directory): Remove NO_COPY.
(windows_system_directory_length): Ditto.
(system_wow64_directory): New variable.
(system_wow64_directory_length): Ditto.
* select.cc (cygwin_select): Don't issue a EINTR on non-main threads
since that seems to be what Linux does. Add missing break to signal
case/switch.
(select_stuff::wait): Don't issue a EINTR on non-main threads since
that seems to be what Linux does. Remove now-unneeded accommodation
for WAIT_IO_COMPLETION. Add a comment.
* sigproc.h (cygwait): Ditto. Don't return if signal_received noticed
and it's not the main thread.
* signal.cc (sigprocmask): Add standard syscall debug stuff.
* thread.cc (pthread_sigmask): Ditto.
2011-12-13 Corinna Vinschen <vinschen@redhat.com> 2011-12-13 Corinna Vinschen <vinschen@redhat.com>
* netdb.cc (open_system_file): Avoid MS-DOS path warning. * netdb.cc (open_system_file): Avoid MS-DOS path warning.

View File

@ -638,12 +638,23 @@ child_info_spawn::handle_spawn ()
static void static void
init_windows_system_directory () init_windows_system_directory ()
{ {
windows_system_directory_length = if (!windows_system_directory_length)
GetSystemDirectoryW (windows_system_directory, MAX_PATH); {
if (windows_system_directory_length == 0) windows_system_directory_length =
api_fatal ("can't find windows system directory"); GetSystemDirectoryW (windows_system_directory, MAX_PATH);
windows_system_directory[windows_system_directory_length++] = L'\\'; if (windows_system_directory_length == 0)
windows_system_directory[windows_system_directory_length] = L'\0'; api_fatal ("can't find windows system directory");
windows_system_directory[windows_system_directory_length++] = L'\\';
windows_system_directory[windows_system_directory_length] = L'\0';
system_wow64_directory_length =
GetSystemWow64DirectoryW (system_wow64_directory, MAX_PATH);
if (system_wow64_directory_length)
{
system_wow64_directory[system_wow64_directory_length++] = L'\\';
system_wow64_directory[system_wow64_directory_length] = L'\0';
}
}
} }
static bool NO_COPY wow64_respawn = false; static bool NO_COPY wow64_respawn = false;

View File

@ -326,10 +326,7 @@ _cygtls::inside_kernel (CONTEXT *cx)
memset (checkdir, 0, size); memset (checkdir, 0, size);
# define h ((HMODULE) m.AllocationBase) # define h ((HMODULE) m.AllocationBase)
/* Apparently Windows 95 can sometimes return bogus addresses from if (!h || m.State != MEM_COMMIT) /* Be defensive */
GetThreadContext. These resolve to a strange allocation base.
These should *never* be treated as interruptible. */
if (!h || m.State != MEM_COMMIT)
res = true; res = true;
else if (h == user_data->hmodule) else if (h == user_data->hmodule)
res = false; res = false;
@ -340,8 +337,12 @@ _cygtls::inside_kernel (CONTEXT *cx)
/* Skip potential long path prefix. */ /* Skip potential long path prefix. */
if (!wcsncmp (checkdir, L"\\\\?\\", 4)) if (!wcsncmp (checkdir, L"\\\\?\\", 4))
checkdir += 4; checkdir += 4;
res = !wcsncasecmp (windows_system_directory, checkdir, res = wcsncasecmp (windows_system_directory, checkdir,
windows_system_directory_length); windows_system_directory_length) == 0;
if (!res && system_wow64_directory_length)
res = wcsncasecmp (system_wow64_directory, checkdir,
system_wow64_directory_length) == 0;
} }
sigproc_printf ("pc %p, h %p, inside_kernel %d", cx->Eip, h, res); sigproc_printf ("pc %p, h %p, inside_kernel %d", cx->Eip, h, res);
# undef h # undef h
@ -828,7 +829,6 @@ set_sig_errno (int e)
{ {
*_my_tls.errno_addr = e; *_my_tls.errno_addr = e;
_my_tls.saved_errno = e; _my_tls.saved_errno = e;
// sigproc_printf ("errno %d", e);
} }
static int setup_handler (int, void *, struct sigaction&, _cygtls *tls) static int setup_handler (int, void *, struct sigaction&, _cygtls *tls)
@ -1328,9 +1328,9 @@ _cygtls::call_signal_handler ()
else if (this != _main_tls) else if (this != _main_tls)
{ {
_main_tls->lock (); _main_tls->lock ();
if (_main_tls->sig) if (_main_tls->sig && _main_tls->incyg)
{ {
paranoid_printf ("Redirecting to main_tls signal %d", _main_tls->sig); small_printf ("Redirecting to main_tls signal %d", _main_tls->sig);
sig = _main_tls->sig; sig = _main_tls->sig;
sa_flags = _main_tls->sa_flags; sa_flags = _main_tls->sa_flags;
func = _main_tls->func; func = _main_tls->func;
@ -1373,7 +1373,7 @@ _cygtls::call_signal_handler ()
} }
unlock (); unlock ();
return this_sa_flags & SA_RESTART; return this_sa_flags & SA_RESTART || (this != _main_tls);
} }
void void

View File

@ -23,8 +23,10 @@ HANDLE NO_COPY hProcToken;
HANDLE NO_COPY hProcImpToken; HANDLE NO_COPY hProcImpToken;
HMODULE NO_COPY cygwin_hmodule; HMODULE NO_COPY cygwin_hmodule;
int NO_COPY sigExeced; int NO_COPY sigExeced;
WCHAR NO_COPY windows_system_directory[MAX_PATH]; WCHAR windows_system_directory[MAX_PATH];
UINT NO_COPY windows_system_directory_length; UINT windows_system_directory_length;
WCHAR system_wow64_directory[MAX_PATH];
UINT system_wow64_directory_length;
/* program exit the program */ /* program exit the program */

View File

@ -129,23 +129,28 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
fd_set *w = allocfd_set (maxfds); fd_set *w = allocfd_set (maxfds);
fd_set *e = allocfd_set (maxfds); fd_set *e = allocfd_set (maxfds);
int res = 1; int res = 0;
/* Degenerate case. No fds to wait for. Just wait. */ /* Degenerate case. No fds to wait for. Just wait. */
if (sel.start.next == NULL) if (sel.start.next == NULL)
switch (cygwait (ms)) while (!res)
{ switch (cygwait (ms))
case WAIT_OBJECT_0: {
select_printf ("signal received"); case WAIT_OBJECT_0:
set_sig_errno (EINTR); _my_tls.call_signal_handler ();
res = -1; if (&_my_tls != _main_tls)
case WAIT_OBJECT_0 + 1: continue; /* Emulate linux behavior */
sel.destroy (); select_printf ("signal received");
pthread::static_cancel_self (); set_sig_errno (EINTR);
/*NOTREACHED*/ res = -1;
default: break;
res = 1; case WAIT_OBJECT_0 + 1:
break; sel.destroy ();
} pthread::static_cancel_self ();
/*NOTREACHED*/
default:
res = 1; /* temporary flag. Will be set to zero below. */
break;
}
else if (sel.always_ready || ms == 0) else if (sel.always_ready || ms == 0)
res = 0; res = 0;
else else
@ -321,12 +326,11 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
MWMO_INPUTAVAILABLE); MWMO_INPUTAVAILABLE);
switch (wait_ret) switch (wait_ret)
{ {
case WAIT_IO_COMPLETION:
syscall_printf ("woke due to apc");
continue; /* Keep going */
break;
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
_my_tls.call_signal_handler ();
if (&_my_tls != _main_tls)
continue; /* Emulate linux behavior */
cleanup (); cleanup ();
select_printf ("signal received"); select_printf ("signal received");
set_sig_errno (EINTR); set_sig_errno (EINTR);
@ -338,6 +342,8 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
destroy (); destroy ();
pthread::static_cancel_self (); pthread::static_cancel_self ();
} }
/* This wasn't a cancel event. It was just a normal object to wait
for. */
break; break;
case WAIT_FAILED: case WAIT_FAILED:
cleanup (); cleanup ();
@ -350,7 +356,7 @@ select_stuff::wait (fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
select_printf ("timed out"); select_printf ("timed out");
res = 1; res = 1;
goto out; goto out;
} }
select_printf ("woke up. wait_ret %d. verifying", wait_ret); select_printf ("woke up. wait_ret %d. verifying", wait_ret);
s = &start; s = &start;

View File

@ -182,8 +182,12 @@ sigprocmask (int how, const sigset_t *set, sigset_t *oldset)
{ {
int res = handle_sigprocmask (how, set, oldset, _my_tls.sigmask); int res = handle_sigprocmask (how, set, oldset, _my_tls.sigmask);
if (res) if (res)
set_errno (res); {
return res ? -1 : 0; set_errno (res);
res = -1;
}
syscall_printf ("%R = sigprocmask (%d, %p, %p)", res, set, oldset);
return res;
} }
int __stdcall int __stdcall

View File

@ -100,7 +100,7 @@ cygwait (HANDLE h, DWORD howlong = INFINITE)
n++; n++;
DWORD res; DWORD res;
while ((res = WaitForMultipleObjects (n, w4, FALSE, howlong)) == wait_signal while ((res = WaitForMultipleObjects (n, w4, FALSE, howlong)) == wait_signal
&& _my_tls.call_signal_handler ()) && (_my_tls.call_signal_handler () || &_my_tls != _main_tls))
continue; continue;
return res; return res;
} }

View File

@ -3087,7 +3087,9 @@ pthread_kill (pthread_t thread, int sig)
extern "C" int extern "C" int
pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set) pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set)
{ {
return handle_sigprocmask (operation, set, old_set, _my_tls.sigmask); int res = handle_sigprocmask (operation, set, old_set, _my_tls.sigmask);
syscall_printf ("%d = pthread_sigmask(%d, %p, %p)", operation, set, old_set);
return res;
} }
/* ID */ /* ID */