From b9bfa8ed7ff665d8896ec77b8417a33017edf11e Mon Sep 17 00:00:00 2001 From: Bryce Denney Date: Thu, 5 Sep 2002 07:48:39 +0000 Subject: [PATCH] - fix signal handling in wxWindows. The problem was that a signal gets delivered to both the GUI and simulator thread, so they both call bx_signal_handler. This can lead to deadlock as multiple threads enter BX_PANIC and try to show a dialog box at once. To solve the problem, I made a function isSimThread() which can be called from anywhere. If the bx_signal_handler is called from any thread OTHER THAN the simulation thread, it returns without doing anything. As a result, only one thread is allowed to enter the signal handler code, and now control-C works correctly. --- bochs/gui/siminterface.h | 8 +++++++- bochs/gui/wxmain.cc | 12 +++++++++++- bochs/gui/wxmain.h | 3 ++- bochs/main.cc | 16 ++++++++++++++-- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/bochs/gui/siminterface.h b/bochs/gui/siminterface.h index 29d998dfa..c692de945 100644 --- a/bochs/gui/siminterface.h +++ b/bochs/gui/siminterface.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: siminterface.h,v 1.57 2002-09-05 07:01:30 bdenney Exp $ +// $Id: siminterface.h,v 1.58 2002-09-05 07:48:38 bdenney Exp $ ///////////////////////////////////////////////////////////////////////// // // Before I can describe what this file is for, I have to make the @@ -874,3 +874,9 @@ extern bx_simulator_interface_c *SIM; extern void bx_init_siminterface (); extern void bx_init_main (int argc, char *argv[]); extern int bx_continue_after_config_interface (int argc, char *argv[]); + +#if BX_WITH_WX +// returns true if called from the simulator thread. +// defined in wxmain.cc, usable anywhere. +bool isSimThread (); +#endif diff --git a/bochs/gui/wxmain.cc b/bochs/gui/wxmain.cc index b2ea28396..b561af968 100644 --- a/bochs/gui/wxmain.cc +++ b/bochs/gui/wxmain.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////// -// $Id: wxmain.cc,v 1.34 2002-09-05 07:01:30 bdenney Exp $ +// $Id: wxmain.cc,v 1.35 2002-09-05 07:48:39 bdenney Exp $ ///////////////////////////////////////////////////////////////// // // wxmain.cc implements the wxWindows frame, toolbar, menus, and dialogs. @@ -72,6 +72,16 @@ MyFrame *theFrame = NULL; MyPanel *thePanel = NULL; +bool isSimThread () { + wxThread *current = wxThread::This (); + if (current == (wxThread*) theFrame->GetSimThread ()) { + wxLogDebug ("isSimThread? yes"); + return true; + } + wxLogDebug ("isSimThread? no"); + return false; +} + ////////////////////////////////////////////////////////////////////// // class declarations ////////////////////////////////////////////////////////////////////// diff --git a/bochs/gui/wxmain.h b/bochs/gui/wxmain.h index 2f941d85b..f38b5f05c 100644 --- a/bochs/gui/wxmain.h +++ b/bochs/gui/wxmain.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////// -// $Id: wxmain.h,v 1.18 2002-09-03 05:32:49 bdenney Exp $ +// $Id: wxmain.h,v 1.19 2002-09-05 07:48:39 bdenney Exp $ ///////////////////////////////////////////////////////////////// // This file defines variables and classes that the wxWindows .cc files // share. It should be included only by wx.cc and wxmain.cc. @@ -161,6 +161,7 @@ public: // called from the sim thread's OnExit() method. void OnSimThreadExit (); + SimThread *GetSimThread () { return sim_thread; } private: wxCriticalSection sim_thread_lock; diff --git a/bochs/main.cc b/bochs/main.cc index 05ee5fc7f..0954f81a6 100644 --- a/bochs/main.cc +++ b/bochs/main.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: main.cc,v 1.136 2002-09-05 07:01:28 bdenney Exp $ +// $Id: main.cc,v 1.137 2002-09-05 07:48:38 bdenney Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 MandrakeSoft S.A. @@ -1477,7 +1477,7 @@ bx_init_hardware() BX_DEBUG(("bx_init_hardware is setting signal handlers")); // if not using debugger, then we can take control of SIGINT. // If using debugger, it needs control of this. -#if BX_DEBUGGER==0 +#if !BX_DEBUGGER /* && !BX_WITH_WX seems like an improvement */ signal(SIGINT, bx_signal_handler); #endif @@ -2757,6 +2757,18 @@ bx_write_configuration (char *rc, int overwrite) void bx_signal_handler( int signum) { +#if BX_WITH_WX + // in a multithreaded environment, a signal such as SIGINT can be sent to all + // threads. This function is only intended to handle signals in the + // simulator thread. It will simply return if called from any other thread. + // Otherwise the BX_PANIC() below can be called in multiple threads at + // once, leading to multiple threads trying to display a dialog box, + // leading to GUI deadlock. + if (!isSimThread ()) { + BX_INFO (("bx_signal_handler: ignored sig %d because it wasn't called from the simulator thread", signum)); + return; + } +#endif #if BX_GUI_SIGHANDLER // GUI signal handler gets first priority, if the mask says it's wanted if ((1<