Bug fix for Qt GUI when closing ROM while the emulation thread is haning on a breakpoint. Now the thread is allowed to complete its frame so that it is idle with a minimal call stack before the ROM is closed. This prevents the emulation thread from coming out of its breakpoint wait loop at attempting to continue running its frame with no ROM data loaded. This fixes a segmentation fault crash that was mentioned in the project Qt issues thread.

This commit is contained in:
mjbudd77 2021-05-02 19:45:36 -04:00
parent a74c2ae80b
commit b97bf287b2
4 changed files with 41 additions and 3 deletions

View File

@ -76,6 +76,7 @@ static std::list <ConsoleDebugger*> dbgWinList;
static void DeleteBreak(int sel); static void DeleteBreak(int sel);
static bool waitingAtBp = false; static bool waitingAtBp = false;
static bool bpDebugEnable = true;
static int lastBpIdx = 0; static int lastBpIdx = 0;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ConsoleDebugger::ConsoleDebugger(QWidget *parent) ConsoleDebugger::ConsoleDebugger(QWidget *parent)
@ -2565,11 +2566,16 @@ void ConsoleDebugger::vbarChanged(int value)
asmView->setLine( value ); asmView->setLine( value );
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void bpDebugSetEnable(bool val)
{
bpDebugEnable = val;
}
//----------------------------------------------------------------------------
void FCEUD_DebugBreakpoint( int bpNum ) void FCEUD_DebugBreakpoint( int bpNum )
{ {
std::list <ConsoleDebugger*>::iterator it; std::list <ConsoleDebugger*>::iterator it;
if ( !nes_shm->runEmulator ) if ( !nes_shm->runEmulator || !bpDebugEnable )
{ {
return; return;
} }
@ -2585,7 +2591,8 @@ void FCEUD_DebugBreakpoint( int bpNum )
(*it)->breakPointNotify( bpNum ); (*it)->breakPointNotify( bpNum );
} }
while ( nes_shm->runEmulator && FCEUI_EmulationPaused() && !FCEUI_EmulationFrameStepped()) while ( nes_shm->runEmulator && bpDebugEnable &&
FCEUI_EmulationPaused() && !FCEUI_EmulationFrameStepped())
{ {
// HACK: break when Frame Advance is pressed // HACK: break when Frame Advance is pressed
extern bool frameAdvanceRequested; extern bool frameAdvanceRequested;
@ -2617,6 +2624,11 @@ bool debuggerWindowIsOpen(void)
return (dbgWinList.size() > 0); return (dbgWinList.size() > 0);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool debuggerWaitingAtBreakpoint(void)
{
return waitingAtBp;
}
//----------------------------------------------------------------------------
void updateAllDebuggerWindows( void ) void updateAllDebuggerWindows( void )
{ {
std::list <ConsoleDebugger*>::iterator it; std::list <ConsoleDebugger*>::iterator it;

View File

@ -344,6 +344,8 @@ class ConsoleDebugger : public QDialog
}; };
bool debuggerWindowIsOpen(void); bool debuggerWindowIsOpen(void);
bool debuggerWaitingAtBreakpoint(void);
void bpDebugSetEnable(bool val);
void saveGameDebugBreakpoints(void); void saveGameDebugBreakpoints(void);
void loadGameDebugBreakpoints(void); void loadGameDebugBreakpoints(void);
void debuggerClearAllBreakpoints(void); void debuggerClearAllBreakpoints(void);

View File

@ -48,6 +48,7 @@
#include "../../input.h" #include "../../input.h"
#include "../../movie.h" #include "../../movie.h"
#include "../../version.h" #include "../../version.h"
#include "common/os_utils.h"
#ifdef _S9XLUA_H #ifdef _S9XLUA_H
#include "../../fceulua.h" #include "../../fceulua.h"

View File

@ -384,6 +384,29 @@ CloseGame(void)
if (!isloaded) { if (!isloaded) {
return(0); return(0);
} }
// If the emulation thread is stuck hanging at a breakpoint,
// disable breakpoint debugging and wait for the thread to
// complete its frame. So that it is idle with a minimal call
// stack when we close the ROM. After thread has completed the
// frame, it is then safe to re-enable breakpoint debugging.
if ( debuggerWaitingAtBreakpoint() )
{
bpDebugSetEnable(false);
if ( fceuWrapperIsLocked() )
{
fceuWrapperUnLock();
msleep(100);
fceuWrapperLock();
}
else
{
msleep(100);
}
bpDebugSetEnable(true);
}
hexEditorSaveBookmarks(); hexEditorSaveBookmarks();
saveGameDebugBreakpoints(); saveGameDebugBreakpoints();
debuggerClearAllBreakpoints(); debuggerClearAllBreakpoints();