- 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.
This commit is contained in:
Bryce Denney 2002-09-05 07:48:39 +00:00
parent b79630a14e
commit b9bfa8ed7f
4 changed files with 34 additions and 5 deletions

View File

@ -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

View File

@ -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
//////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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<<signum) & bx_gui.get_sighandler_mask ()) {