Skip to content

Commit

Permalink
Fix/prevent crashes when MainWindow is closed before LoadFile() compl…
Browse files Browse the repository at this point in the history
…etes, or when it gets certain messages before TheThread completes initialization.

Fix missing ppsspp.ini loading log (only 1 unimportant line though).
Fix loading ui_atlas.zim failure when [General]Browse = True is set in ppsspp.ini.
Some other minor fixes as well.
  • Loading branch information
aquanull committed Jun 15, 2013
1 parent ce2c18d commit bb5fce6
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 61 deletions.
6 changes: 3 additions & 3 deletions Common/ConsoleListener.cpp
Expand Up @@ -101,7 +101,7 @@ void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title
if (hTriggerEvent != NULL && hThread == NULL)
{
logPending = new char[LOG_PENDING_MAX];
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &ConsoleListener::RunThread, this, 0, NULL);
hThread = (HANDLE)_beginthreadex(NULL, 0, &ConsoleListener::RunThread, this, 0, NULL);
}
#endif
}
Expand Down Expand Up @@ -246,9 +246,9 @@ COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth)
return Ret;
}

DWORD WINAPI ConsoleListener::RunThread(LPVOID lpParam)
unsigned int WINAPI ConsoleListener::RunThread(void *lpParam)
{
ConsoleListener *consoleLog = (ConsoleListener *) lpParam;
ConsoleListener *consoleLog = (ConsoleListener *)lpParam;
consoleLog->LogWriterThread();
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion Common/ConsoleListener.h
Expand Up @@ -50,7 +50,7 @@ class ConsoleListener : public LogListener
HWND GetHwnd(void);
HANDLE hConsole;

static DWORD WINAPI RunThread(LPVOID lpParam);
static unsigned int WINAPI RunThread(void *lpParam);
void LogWriterThread();
void SendToThread(LogTypes::LOG_LEVELS Level, const char *Text);
void WriteToConsole(LogTypes::LOG_LEVELS Level, const char *Text, size_t Len);
Expand Down
7 changes: 6 additions & 1 deletion Core/Core.cpp
Expand Up @@ -70,14 +70,19 @@ bool Core_IsStepping()
return coreState == CORE_STEPPING || coreState == CORE_POWERDOWN;
}

bool Core_IsActive()
{
return coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME || coreStatePending;
}

bool Core_IsInactive()
{
return coreState != CORE_RUNNING && coreState != CORE_NEXTFRAME && !coreStatePending;
}

void Core_WaitInactive()
{
while (!Core_IsInactive())
while (Core_IsActive())
m_hInactiveEvent.wait(m_hInactiveMutex);
}

Expand Down
1 change: 1 addition & 0 deletions Core/Core.h
Expand Up @@ -33,6 +33,7 @@ void Core_Halt(const char *msg);

bool Core_IsStepping();

bool Core_IsActive();
bool Core_IsInactive();
void Core_WaitInactive();
void Core_WaitInactive(int milliseconds);
Expand Down
3 changes: 2 additions & 1 deletion Core/System.cpp
Expand Up @@ -97,7 +97,8 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
// TODO: Check Game INI here for settings, patches and cheats, and modify coreParameter accordingly

std::string filename = coreParameter.fileToStart;
if (!LoadFile(filename, error_string)) {
if (!LoadFile(filename, error_string) || coreState == CORE_POWERDOWN)
{
pspFileSystem.Shutdown();
CoreTiming::Shutdown();
__KernelShutdown();
Expand Down
5 changes: 2 additions & 3 deletions Windows/DSoundStream.cpp
Expand Up @@ -110,7 +110,7 @@ namespace DSound
int lastPos;
short realtimeBuffer[BUFSIZE * 2];

DWORD WINAPI soundThread(void *)
unsigned int WINAPI soundThread(void *)
{
currentPos = 0;
lastPos = 0;
Expand Down Expand Up @@ -175,8 +175,7 @@ namespace DSound
memset(p1,0,num1);
dsBuffer->Unlock(p1,num1,0,0);
totalRenderedBytes = -bufferSize;
DWORD h;
hThread = CreateThread(0,0,soundThread,0,0,&h);
hThread = (HANDLE)_beginthreadex(0, 0, soundThread, 0, 0, 0);
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion Windows/Debugger/Debugger_Disasm.cpp
Expand Up @@ -228,7 +228,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)

case IDC_MEMCHECK:
{
bool isRunning = !Core_IsInactive();
bool isRunning = Core_IsActive();
if (isRunning)
{
SetDebugMode(true);
Expand Down
79 changes: 71 additions & 8 deletions Windows/EmuThread.cpp
Expand Up @@ -7,6 +7,8 @@
#include "StringUtils.h"
#include "../Globals.h"
#include "EmuThread.h"
#include "WndMainWindow.h"
#include "resource.h"
#include "../Core/Reporting.h"
#include "../Core/MemMap.h"
#include "../Core/Core.h"
Expand All @@ -17,34 +19,79 @@

#include <tchar.h>
#include <process.h>
#include <intrin.h>
#pragma intrinsic(_InterlockedExchange)

class EmuThreadLockGuard
{
public:
EmuThreadLockGuard() { emuThreadCS_.Enter(); }
~EmuThreadLockGuard() { emuThreadCS_.Leave(); }
private:
static struct EmuThreadCS
{
EmuThreadCS() { InitializeCriticalSection(&TheCS_); }
~EmuThreadCS() { DeleteCriticalSection(&TheCS_); }
void Enter() { EnterCriticalSection(&TheCS_); }
void Leave() { LeaveCriticalSection(&TheCS_); }
CRITICAL_SECTION TheCS_;
} emuThreadCS_;
};

EmuThreadLockGuard::EmuThreadCS EmuThreadLockGuard::emuThreadCS_;
static HANDLE emuThread;
static long emuThreadReady;

enum EmuTreadStatus : long
{
THREAD_NONE = 0,
THREAD_INIT,
THREAD_CORE_LOOP,
THREAD_SHUTDOWN,
THREAD_END,
};

HANDLE EmuThread_GetThreadHandle()
{
EmuThreadLockGuard lock;
return emuThread;
}

DWORD TheThread(LPVOID x);
unsigned int WINAPI TheThread(void *);

void EmuThread_Start()
{
unsigned int i;
emuThread = (HANDLE)_beginthreadex(0,0,(unsigned int (__stdcall *)(void *))TheThread,(LPVOID)0,0,&i);
EmuThreadLockGuard lock;
emuThread = (HANDLE)_beginthreadex(0, 0, &TheThread, 0, 0, 0);
}

void EmuThread_Stop()
{
// DSound_UpdateSound();
Core_Stop();
if (WAIT_TIMEOUT == WaitForSingleObject(EmuThread_GetThreadHandle(),300))
Core_WaitInactive(800);
if (WAIT_TIMEOUT == WaitForSingleObject(emuThread, 800))
{
MessageBox(MainWindow::GetHWND(),"Wait for emuthread timed out! :(\n"
"please alert the developer to possible deadlock or infinite loop in emuthread!", 0, 0);
}
{
//MessageBox(0,"Wait for emuthread timed out, please alert the developer to possible deadlock or infinite loop in emuthread :(.",0,0);
EmuThreadLockGuard lock;
CloseHandle(emuThread);
emuThread = 0;
}
host->UpdateUI();
}

DWORD TheThread(LPVOID x) {
bool EmuThread_Ready()
{
return emuThreadReady == THREAD_CORE_LOOP;
}

unsigned int WINAPI TheThread(void *)
{
_InterlockedExchange(&emuThreadReady, THREAD_INIT);

setCurrentThreadName("EmuThread");

std::string memstick, flash0;
Expand Down Expand Up @@ -75,20 +122,36 @@ DWORD TheThread(LPVOID x) {
INFO_LOG(BOOT, "Done.");
_dbg_update_();

if (coreState == CORE_POWERDOWN) {
INFO_LOG(BOOT, "Exit before core loop.");
goto shutdown;
}

_InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP);

if (g_Config.bBrowse)
{
PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0);
//MainWindow::BrowseAndBoot("");
}

Core_EnableStepping(FALSE);

Core_Run();

shutdown:
_InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN);

host = nativeHost;
NativeShutdownGraphics();
NativeShutdown();
host = oldHost;

host->ShutdownGL();

_InterlockedExchange(&emuThreadReady, THREAD_END);

//The CPU should return when a game is stopped and cleanup should be done here,
//so we can restart the plugins (or load new ones) for the next game
_endthreadex(0);
return 0;
}

Expand Down
20 changes: 19 additions & 1 deletion Windows/EmuThread.h
@@ -1,4 +1,22 @@
// Copyright (c) 2013- PPSSPP Project.

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.

// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/

// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.

#pragma once

void EmuThread_Start();
void EmuThread_Stop();
void EmuThread_Stop();
bool EmuThread_Ready();
49 changes: 26 additions & 23 deletions Windows/WndMainWindow.cpp
Expand Up @@ -214,18 +214,21 @@ namespace MainWindow
if (zoom < 1) zoom = 1;
if (zoom > 4) zoom = 4;

RECT rc,rcOrig;
RECT rc, rcOrig;
GetWindowRectAtZoom(zoom, rcOrig, rc);

u32 style = WS_OVERLAPPEDWINDOW;

hwndMain = CreateWindowEx(0,szWindowClass, "", style,
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, hInstance, NULL);
SetTimer(hwndMain, TIMER_CURSORUPDATE, CURSORUPDATE_INTERVAL_MS, 0);
SetPlaying(0);
rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
if (!hwndMain)
return FALSE;

hwndDisplay = CreateWindowEx(0, szDisplayClass, TEXT(""), WS_CHILD | WS_VISIBLE,
rcOrig.left, rcOrig.top, rcOrig.right - rcOrig.left, rcOrig.bottom - rcOrig.top, hwndMain, 0, hInstance, 0);
if (!hwndDisplay)
return FALSE;

menu = GetMenu(hwndMain);
#ifdef FINAL
RemoveMenu(menu,2,MF_BYPOSITION);
Expand All @@ -241,20 +244,22 @@ namespace MainWindow
{
SetMenuInfo(GetSubMenu(menu,i),&info);
}
UpdateMenus();

hwndDisplay = CreateWindowEx(0,szDisplayClass,TEXT(""),
WS_CHILD|WS_VISIBLE,
0,0,/*rcOrig.left,rcOrig.top,*/rcOrig.right-rcOrig.left,rcOrig.bottom-rcOrig.top,hwndMain,0,hInstance,0);

ShowWindow(hwndMain, nCmdShow);
//accept dragged files
DragAcceptFiles(hwndMain, TRUE);

SetTimer(hwndMain, TIMER_CURSORUPDATE, CURSORUPDATE_INTERVAL_MS, 0);

Update();
SetPlaying(0);

ShowWindow(hwndMain, nCmdShow);

#if ENABLE_TOUCH
RegisterTouchWindow(hwndDisplay, TWF_WANTPALM);
#endif

SetFocus(hwndMain);
SetFocus(hwndDisplay);

return TRUE;
Expand Down Expand Up @@ -429,6 +434,8 @@ namespace MainWindow

case WM_COMMAND:
{
if (!EmuThread_Ready())
return DefWindowProc(hWnd, message, wParam, lParam);
I18NCategory *g = GetI18NCategory("Graphics");

wmId = LOWORD(wParam);
Expand Down Expand Up @@ -735,6 +742,9 @@ namespace MainWindow

case WM_DROPFILES:
{
if (!EmuThread_Ready())
return DefWindowProc(hWnd, message, wParam, lParam);

HDROP hdrop = (HDROP)wParam;
int count = DragQueryFile(hdrop,0xFFFFFFFF,0,0);
if (count != 1)
Expand All @@ -760,21 +770,14 @@ namespace MainWindow
break;

case WM_CLOSE:
Core_Stop();
Core_WaitInactive(200);
/*
if (g_Config.bConfirmOnQuit && __KernelIsRunning())
if (IDYES != MessageBox(hwndMain, "A game is in progress. Are you sure you want to exit?",
"Are you sure?", MB_YESNO | MB_ICONQUESTION))
return 0;
//*/
EmuThread_Stop();

/*
if (g_Config.bConfirmOnQuit && CCore::IsRunning())
{
if (IDNO==MessageBox(hwndMain,"A game is in progress. Are you sure you want to exit?","Are you sure?",MB_YESNO|MB_ICONQUESTION))
return 1;//or 1?
else
return DefWindowProc(hWnd,message,wParam,lParam);
break;
}
else
*/
return DefWindowProc(hWnd,message,wParam,lParam);

case WM_DESTROY:
Expand Down

0 comments on commit bb5fce6

Please sign in to comment.