* 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:
parent
8d1bda71b4
commit
45d7b637fa
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue