about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--elf/rtld.c3
-rw-r--r--hurd/hurdsig.c40
-rw-r--r--sysdeps/mach/hurd/sigaction.c8
4 files changed, 50 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 970be16c4f..47cacbdd0f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
+Thu Jun  6 16:12:39 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* hurd/hurdsig.c (_hurd_internal_post_signal): For SIGNO==0 pending
+	check, deliver a pending blocked signal if its action might be to
+	ignore.
+	* sysdeps/mach/hurd/sigaction.c: If new action is SIG_IGN or SIG_DFL
+	and SIG is pending, wake up signal thread to check us.
+
+	* hurd/hurdsig.c (_hurd_internal_post_signal): Don't mark a signal
+	pending while blocked or stopped when the action is to ignore it.
+
 Thu Jun  6 12:56:03 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
 
+	* hurd/hurdsig.c (_hurd_internal_post_signal: resume): Only set
+	SS_SUSPENDED when the thread is really suspended.
+
+	* elf/rtld.c (dl_main): Don't dereference _dl_rtld_map.l_next if null.
+
 	* Makerules (headers): Move append of $(sysdep_headers) after include
 	of sysdep makefiles.
 
diff --git a/elf/rtld.c b/elf/rtld.c
index 032bb8ee87..b34d8598bb 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -263,7 +263,8 @@ of this helper program; chances are you did not intend to run this program.\n",
       /* No DT_NEEDED entry referred to the interpreter object itself,
 	 so remove it from the list of visible objects.  */
       _dl_rtld_map.l_prev->l_next = _dl_rtld_map.l_next;
-      _dl_rtld_map.l_next->l_prev = _dl_rtld_map.l_prev;
+      if (_dl_rtld_map.l_next)
+	_dl_rtld_map.l_next->l_prev = _dl_rtld_map.l_prev;
     }
 
   if (list_only)
diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
index 6abad33021..f2bc08993d 100644
--- a/hurd/hurdsig.c
+++ b/hurd/hurdsig.c
@@ -516,8 +516,9 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
 		       (vm_address_t) threads,
 		       nthreads * sizeof *threads);
       _hurd_stopped = 0;
-      /* The thread that will run the handler is already suspended.  */
-      ss_suspended = 1;
+      if (act == handle)
+	/* The thread that will run the handler is already suspended.  */
+	ss_suspended = 1;
     }
 
   if (signo == 0)
@@ -673,19 +674,11 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
     }
 
   /* Handle receipt of a blocked signal, or any signal while stopped.  */
-  if (__sigismember (&ss->blocked, signo) ||
+  if (act != ignore &&		/* Signals ignored now are forgotten now.  */
+      __sigismember (&ss->blocked, signo) ||
       (signo != SIGKILL && _hurd_stopped))
     {
       mark_pending ();
-      /* If there was a call to resume above in SIGCONT processing
-	 and we've left a thread suspended, now's the time to
-	 set it going. */
-      if (ss_suspended)
-	{
-	  err = __thread_resume (ss->thread);
-	  assert_perror (err);
-	  ss_suspended = 0;
-	}
       act = ignore;
     }
 
@@ -708,7 +701,15 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
       break;
 
     case ignore:
-      /* Nobody cares about this signal.  */
+      /* Nobody cares about this signal.  If there was a call to resume
+	 above in SIGCONT processing and we've left a thread suspended,
+	 now's the time to set it going. */
+      if (ss_suspended)
+	{
+	  err = __thread_resume (ss->thread);
+	  assert_perror (err);
+	  ss_suspended = 0;
+	}
       break;
 
     sigbomb:
@@ -904,10 +905,10 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
 
     if (signals_pending ())
       {
-      pending:
 	for (signo = 1; signo < NSIG; ++signo)
 	  if (__sigismember (&pending, signo))
 	    {
+	    deliver:
 	      __sigdelset (&ss->pending, signo);
 	      *detail = ss->pending_data[signo];
 	      __spin_unlock (&ss->lock);
@@ -925,8 +926,15 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
 	for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
 	  {
 	    __spin_lock (&ss->lock);
-	    if (signals_pending ())
-	      goto pending;
+	    for (signo = 1; signo < NSIG; ++signo)
+	      if (__sigismember (&ss->pending, signo) &&
+		  !__sigismember (&ss->blocked, signo) ||
+		  /* We "deliver" immediately pending blocked signals whose
+                     action might be to ignore, so that if ignored they are
+                     dropped right away.  */
+		  ss->actions[signo].sa_handler == SIG_IGN ||
+		  ss->actions[signo].sa_handler == SIG_DFL)
+		goto deliver_pending;
 	    __spin_unlock (&ss->lock);
 	  }
 	__mutex_unlock (&_hurd_siglock);
diff --git a/sysdeps/mach/hurd/sigaction.c b/sysdeps/mach/hurd/sigaction.c
index ebe70664be..df28131281 100644
--- a/sysdeps/mach/hurd/sigaction.c
+++ b/sysdeps/mach/hurd/sigaction.c
@@ -67,6 +67,14 @@ DEFUN(__sigaction, (sig, act, oact),
       __spin_lock (&ss->lock);
       pending = ss->pending & ~ss->blocked;
     }
+  else if (a.sa_handler == SIG_IGN || a.sa_handler == SIG_DFL)
+    /* We are changing to an action that might be to ignore SIG signals.
+       If SIG is blocked and pending and the new action is to ignore it, we
+       must remove it from the pending set now; if the action is changed
+       back and then SIG is unblocked, the signal pending now should not
+       arrive.  So wake up the signal thread to check the new state and do
+       the right thing.  */
+    pending = ss->pending & __sigmask (sig);
   else
     pending = 0;