[haiku-commits] r41709 - in haiku/branches/developer/bonefish/signals: headers/private/kernel src/system/kernel

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 24 May 2011 15:33:58 +0200 (CEST)

Author: bonefish
Date: 2011-05-24 15:33:58 +0200 (Tue, 24 May 2011)
New Revision: 41709
Changeset: https://dev.haiku-os.org/changeset/41709

Modified:
   haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h
   haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp
   haiku/branches/developer/bonefish/signals/src/system/kernel/thread.cpp
Log:
* handle_signals(): When handling a stop signal suspend the thread right there
  instead of returning and letting the caller (thread_at_kernel_exit()) do that.
* Before suspending the thread, but when already holding the scheduler lock,
  check whether there are pending continue/kill signals. This remedies a race
  condition with the signal delivery code, which, upon delivery of such a
  signal, unsuspends the thread, but of course only when it was already
  suspended, not when it was about to be suspended.
  The race conditiion could be seen almost reliably with the new
  SIGNAL_CONTINUE_THREAD signal, since it doesn't clear the pending stop
  signals, so that it was likely with the suspend_thread() + resume_thread() to
  occur.


Modified: 
haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h
===================================================================
--- haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h  
2011-05-24 12:34:05 UTC (rev 41708)
+++ haiku/branches/developer/bonefish/signals/headers/private/kernel/ksignal.h  
2011-05-24 13:33:58 UTC (rev 41709)
@@ -191,7 +191,7 @@
 extern "C" {
 #endif
 
-bool handle_signals(Thread *thread);
+void handle_signals(Thread* thread);
 bool is_team_signal_blocked(Team* team, int signal);
 void signal_get_user_stack(addr_t address, stack_t* stack);
 

Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp
===================================================================
--- haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp      
2011-05-24 12:34:05 UTC (rev 41708)
+++ haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp      
2011-05-24 13:33:58 UTC (rev 41709)
@@ -47,6 +47,8 @@
 #define STOP_SIGNALS \
        (SIGNAL_TO_MASK(SIGSTOP) | SIGNAL_TO_MASK(SIGTSTP) \
        | SIGNAL_TO_MASK(SIGTTIN) | SIGNAL_TO_MASK(SIGTTOU))
+#define CONTINUE_SIGNALS \
+       (SIGNAL_TO_MASK(SIGCONT) | SIGNAL_TO_MASK(SIGNAL_CONTINUE_THREAD))
 #define DEFAULT_IGNORE_SIGNALS \
        (SIGNAL_TO_MASK(SIGCHLD) | SIGNAL_TO_MASK(SIGWINCH) \
        | SIGNAL_TO_MASK(SIGCONT) \
@@ -853,16 +855,15 @@
 }
 
 
-/*! Actually handles the signal -- i.e. the thread will exit, a custom signal
-       handler is prepared, or whatever the signal demands.
+/*! Actually handles pending signals -- i.e. the thread will exit, a custom
+       signal handler is prepared, or whatever the signal demands.
+       The function will not return, when a deadly signal is encountered. The
+       function will suspend the thread indefinitely, when a stop signal is
+       encountered.
        Interrupts must be enabled.
        \param thread The current thread.
-       \return \c true, if a signal was handled that puts the thread to sleep. 
The
-               caller is responsible for suspending the thread. \c false means 
that
-               all pending non-blocked signals have been handled and the 
caller can
-               return to userland.
 */
-bool
+void
 handle_signals(Thread* thread)
 {
        Team* team = thread->team;
@@ -880,7 +881,7 @@
                && (signalMask & NON_DEFERRABLE_SIGNALS) == 0
                && thread->sig_temp_enabled == 0) {
                thread->user_thread->pending_signals = signalMask;
-               return false;
+               return;
        }
 
        thread->user_thread->pending_signals = 0;
@@ -1061,7 +1062,18 @@
                                                team->UnlockTeamAndParent();
                                        }
 
-                                       return true;
+                                       groupLocker.Unlock();
+
+                                       // Suspend the thread, unless there's 
already a signal to
+                                       // continue or kill pending.
+                                       InterruptsSpinLocker 
schedulerLocker(gSchedulerLock);
+                                       if ((thread->AllPendingSignals()
+                                                       & (CONTINUE_SIGNALS | 
KILL_SIGNALS)) == 0) {
+                                               thread->next_state = 
B_THREAD_SUSPENDED;
+                                               scheduler_reschedule();
+                                       }
+
+                                       continue;
                                }
 
                                case SIGSEGV:
@@ -1169,7 +1181,7 @@
                // sigsuspend_internal().
                thread->sig_temp_enabled = 0;
 
-               return false;
+               return;
        }
 
        // We have not handled any signal (respectively only ignored ones).
@@ -1185,8 +1197,6 @@
                // the syscall
                atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL);
        }
-
-       return false;
 }
 
 

Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/thread.cpp
===================================================================
--- haiku/branches/developer/bonefish/signals/src/system/kernel/thread.cpp      
2011-05-24 12:34:05 UTC (rev 41708)
+++ haiku/branches/developer/bonefish/signals/src/system/kernel/thread.cpp      
2011-05-24 13:33:58 UTC (rev 41709)
@@ -1834,11 +1834,7 @@
 
        TRACE(("thread_at_kernel_exit: exit thread %ld\n", thread->id));
 
-       while (handle_signals(thread)) {
-               InterruptsSpinLocker schedulerLocker(gSchedulerLock);
-               thread->next_state = B_THREAD_SUSPENDED;
-               scheduler_reschedule();
-       }
+       handle_signals(thread);
 
        disable_interrupts();
 


Other related posts:

  • » [haiku-commits] r41709 - in haiku/branches/developer/bonefish/signals: headers/private/kernel src/system/kernel - ingo_weinhold