summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <cgf@redhat.com>2004-01-26 22:28:56 +0000
committerChristopher Faylor <cgf@redhat.com>2004-01-26 22:28:56 +0000
commitcc0a722ca48f423dbe73343072cf7a68c91917a9 (patch)
treed312dd7067ed23d0e6c50f04769adf982e94b64b
parent87fa5fcd975b3f2c9554a4b1afcd1199f3c15fc9 (diff)
downloadgdb-cr-0x9e.tar.gz
* exceptions.cc (sig_handle_tty_stop): Avoid races by waiting for bothcvs/cr-0x9ecr-0x9e
signal_arrived and for sigCONT. (sigpacket::process): Enforce sending of both signal_arrived and sigCONT, where appropriate. * gendef (sigreturn): Save tls pointer in ebx so that it can jump into sigdelayed and use the same register.
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/exceptions.cc28
-rwxr-xr-xwinsup/cygwin/gendef223
3 files changed, 254 insertions, 6 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a2d027861c0..54b7cb0efaf 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,14 @@
2004-01-26 Christopher Faylor <cgf@redhat.com>
+ * exceptions.cc (sig_handle_tty_stop): Avoid races by waiting for both
+ signal_arrived and for sigCONT.
+ (sigpacket::process): Enforce sending of both signal_arrived and
+ sigCONT, where appropriate.
+ * gendef (sigreturn): Save tls pointer in ebx so that it can jump into
+ sigdelayed and use the same register.
+
+2004-01-26 Christopher Faylor <cgf@redhat.com>
+
* cygtls.cc (_threadinfo::init_thread): Add more local reent stdio
initialization.
* dcrt0.cc (initial_env): Can it really be true that XP doesn't allow
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 9889d4d260b..49b04c7c87d 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -610,8 +610,19 @@ sig_handle_tty_stop (int sig)
}
sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p",
myself->pid, sig, myself->ppid_handle);
- if (WaitForSingleObject (sigCONT, INFINITE) != WAIT_OBJECT_0)
- api_fatal ("WaitSingleObject failed, %E");
+ HANDLE w4[2];
+ w4[0] = sigCONT;
+ w4[1] = signal_arrived;
+ switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE))
+ {
+ case WAIT_OBJECT_0:
+ case WAIT_OBJECT_0 + 1:
+ reset_signal_arrived ();
+ break;
+ default:
+ api_fatal ("WaitSingleObject failed, %E");
+ break;
+ }
return;
}
}
@@ -891,9 +902,12 @@ set_signal_mask (sigset_t newmask, sigset_t oldmask)
int __stdcall
sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
{
- if (sig == SIGCONT)
+ DWORD continue_now;
+ if (sig != SIGCONT)
+ continue_now = false;
+ else
{
- DWORD stopped = myself->process_state & PID_STOPPED;
+ continue_now = myself->process_state & PID_STOPPED;
myself->stopsig = 0;
myself->process_state &= ~PID_STOPPED;
/* Clear pending stop signals */
@@ -901,8 +915,6 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
sig_clear (SIGTSTP);
sig_clear (SIGTTIN);
sig_clear (SIGTTOU);
- if (stopped)
- SetEvent (sigCONT);
}
int rc = 1;
@@ -952,6 +964,8 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
|| sig == SIGURG)
{
sigproc_printf ("default signal %d ignored", sig);
+ if (continue_now)
+ SetEvent (signal_arrived);
goto done;
}
@@ -985,6 +999,8 @@ dosig:
rc = setup_handler (sig, handler, thissig, tls ?: _main_tls);
done:
+ if (continue_now)
+ SetEvent (sigCONT);
sigproc_printf ("returning %d", rc);
return rc;
diff --git a/winsup/cygwin/gendef b/winsup/cygwin/gendef
new file mode 100755
index 00000000000..7e3a4aef996
--- /dev/null
+++ b/winsup/cygwin/gendef
@@ -0,0 +1,223 @@
+#!/usr/bin/perl
+use strict;
+my $in = shift;
+my $tls_offsets = shift;
+my $out = shift;
+my $sigfe = shift;
+
+$main::first = 0;
+if (!defined($in) || !defined($out) || !defined($sigfe)) {
+ die "usage: $0 deffile.in cygtls.h deffile.def sigfe.s\n";
+}
+
+require $tls_offsets;
+
+open(IN, $in) or die "$0: couldn't open \"$in\" - $!\n";
+my @top = ();
+while (<IN>) {
+ push(@top, $_);
+ last if /^\s*exports\s*$/i;
+}
+my $libline = <IN>;
+my @in = <IN>;
+close(IN);
+
+my %sigfe = ();
+my @data = ();
+my @nosigfuncs = ();
+my @out = ();
+for (@in) {
+ /\sDATA$/o and do {
+ push(@data, $_);
+ next;
+ };
+ chomp;
+ if (/=/o) {
+ if (s/\s+NOSIGFE\s*$//) {
+ } elsif (s/ SIGFE$//) {
+ my $func = (split(' '))[2];
+ $sigfe{$func} = '_sigfe_' . $func;
+ }
+ } else {
+ my ($func, $sigfe) = m%^\s*(\S+)(?:\s+((?:NO)?SIGR?FE))?$%o;
+ if (defined($sigfe) && $sigfe =~ /^NO/o) {
+ $_ = $func;
+ } else {
+ $sigfe ||= 'sigfe';
+ $_ = '_' . lc($sigfe) . '_' . $func;
+ $sigfe{$func} = $_;
+ $_ = $func . ' = ' . $_;
+ }
+ }
+ s/(\S)\s+(\S)/$1 $2/go;
+ s/(\S)\s+$/$1/o;
+ s/^\s+(\S)/$1/o;
+ push(@out, $_ . "\n");
+}
+
+for (@out) {
+ my ($alias, $func) = /^(\S+) = (\S+)\s*$/o;
+ $_ = $alias . ' = ' . $sigfe{$func} . "\n"
+ if defined($func) && $sigfe{$func};
+}
+open(OUT, '>', $out) or die "$0: couldn't open \"$out\" - $!\n";
+print OUT @top, @data, @out;
+close OUT;
+
+open(SIGFE, '>', $sigfe) or die "$0: couldn't open sigfe file \"$sigfe\" - $!\n";
+
+for my $k (sort keys %sigfe) {
+ print SIGFE fefunc($k, $sigfe{$k});
+}
+close SIGFE;
+
+sub fefunc {
+ my $func = '_' . shift;
+ my $fe = '_' . shift;
+ my $extra;
+ my $res = <<EOF;
+ .extern _siglist_index
+ .extern _siglist
+ .extern $func
+ .global $fe
+$fe:
+ pushl \$$func
+ jmp __sigfe
+
+EOF
+ if (!$main::first++) {
+ $res = <<EOF . longjmp () . $res;
+ .text
+ .global __sigbe
+ .global _sigreturn
+ .global _sigdelayed
+
+ .stabs "_sigfe:F(0,1)",36,0,0,__sigbe
+__sigfe:
+ pushl %edx
+ movl %fs:4,%eax
+ movl \$4,%edx
+ xadd %edx,$tls::stackptr(%eax)
+ leal __sigbe,%eax
+ xchg %eax,8(%esp)
+ movl %eax,(%edx)
+ popl %edx
+ ret
+
+ .stabs "_sigbe:F(0,1)",36,0,0,__sigbe
+__sigbe:
+ pushl %eax
+ pushl %edx
+ movl \$-4,%edx
+1: movl %fs:4,%eax
+ xadd %edx,$tls::stackptr(%eax)
+ xorl %eax,%eax
+ lock xchg %eax,-4(%edx)
+ testl %eax,%eax
+ jnz 2f
+ call _low_priority_sleep
+ xorl %edx,%edx
+ jmp 1b
+2: xchg %eax,4(%esp)
+ popl %edx
+ ret
+
+ .stabs "sigreturn:F(0,1)",36,0,0,_sigreturn
+_sigreturn:
+ addl \$4,%esp # Remove argument
+ call _set_process_mask\@4
+
+ movl %fs:4,%ebx
+
+ cmpl \$0,$tls::sig(%ebx) # Did a signal come in?
+ jnz 3f # Yes, if non-zero
+
+1: popl %edx # saved errno
+ testl %edx,%edx # Is it < 0
+ jl 2f # yup. ignore it
+ movl $tls::errno_addr(%ebx),%eax
+ movl %edx,(%eax)
+2: popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %edi
+ popl %esi
+ popf
+ popl %ebp
+ jmp __sigbe
+
+ .stabs "sigdelayed:F(0,1)",36,0,0,_sigdelayed
+_sigdelayed:
+ pushl %ebp
+ movl %esp,%ebp
+ pushf
+ pushl %esi
+ pushl %edi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+ movl %fs:4,%ebx
+ pushl $tls::saved_errno(%ebx) # saved errno
+3: pushl $tls::oldmask(%ebx) # oldmask
+ pushl $tls::sig(%ebx) # signal argument
+ pushl \$_sigreturn
+
+ call _reset_signal_arrived\@0
+ pushl $tls::func(%ebx) # signal func
+ pushl $tls::newmask(%ebx) # newmask - eaten by set_process_mask
+
+ call _set_process_mask\@4
+ movl \$0,$tls::sig(%ebx) # zero the signal number as a
+ # flag to the signal handler thread
+ # that it is ok to set up sigsave
+ popl %ebx
+ jmp *%ebx
+
+EOF
+ }
+ return $res;
+}
+
+sub longjmp {
+ return <<EOF;
+
+ .globl _longjmp
+
+_longjmp:
+ pushl %ebp
+ movl %esp,%ebp
+ movl 8(%ebp),%edi
+ movl 12(%ebp),%eax
+ testl %eax,%eax
+ jne 0f
+ incl %eax
+0:
+ movl %eax,0(%edi)
+ movl 24(%edi),%ebp
+ pushfl
+ popl %ebx
+ movw 42(%edi),%ax
+ movw %ax,%ss
+ movl 28(%edi),%esp
+ pushl 32(%edi)
+ pushl %ebx
+ movw 36(%edi),%ax
+ movw %ax,%es
+ movw 40(%edi),%ax
+ movw %ax,%gs
+ movl %fs:4,%eax
+ leal ($tls::stack)(%eax),%edx
+ movl %edx,($tls::stackptr)(%eax)
+ movl 0(%edi),%eax
+ movl 4(%edi),%ebx
+ movl 8(%edi),%ecx
+ movl 12(%edi),%edx
+ movl 16(%edi),%esi
+ movl 20(%edi),%edi
+ popfl
+ ret
+
+EOF
+}