Fix/prevent crashes when MainWindow is closed before LoadFile() completes, 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.
This commit is contained in:
aquanull 2013-06-08 08:32:07 +08:00
parent ce2c18d2fe
commit bb5fce600e
11 changed files with 144 additions and 61 deletions

View File

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

View File

@ -50,7 +50,7 @@ private:
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);

View File

@ -70,6 +70,11 @@ 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;
@ -77,7 +82,7 @@ bool Core_IsInactive()
void Core_WaitInactive()
{
while (!Core_IsInactive())
while (Core_IsActive())
m_hInactiveEvent.wait(m_hInactiveMutex);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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"
@ -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(0,"Wait for emuthread timed out, please alert the developer to possible deadlock or infinite loop in emuthread :(.",0,0);
MessageBox(MainWindow::GetHWND(),"Wait for emuthread timed out! :(\n"
"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;
@ -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;
}

View File

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

View File

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

View File

@ -64,9 +64,11 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
hideLog = false;
#endif
LogManager::Init();
LogManager::GetInstance()->GetConsoleListener()->Open(hideLog, 150, 120, "PPSSPP Debug Console");
LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LERROR);
g_Config.Load();
VFSRegister("", new DirectoryAssetReader("assets/"));
VFSRegister("", new DirectoryAssetReader(""));
// The rest is handled in NativeInit().
for (int i = 1; i < __argc; ++i)
@ -89,6 +91,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
}
}
VFSRegister("", new DirectoryAssetReader("assets/"));
VFSRegister("", new DirectoryAssetReader(""));
//Windows, API init stuff
INITCOMMONCONTROLSEX comm;
comm.dwSize = sizeof(comm);
@ -97,15 +102,13 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
timeBeginPeriod(1);
MainWindow::Init(_hInstance);
HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS);
g_hPopupMenus = LoadMenu(_hInstance, (LPCSTR)IDR_POPUPMENUS);
MainWindow::Show(_hInstance, iCmdShow);
host = new WindowsHost(MainWindow::GetHWND(), MainWindow::GetDisplayHWND());
HWND hwndMain = MainWindow::GetHWND();
HMENU menu = GetMenu(hwndMain);
HWND hwndDisplay = MainWindow::GetDisplayHWND();
//initialize custom controls
CtrlDisAsmView::init();
CtrlMemView::init();
@ -114,25 +117,15 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
DialogManager::AddDlg(memoryWindow[0] = new CMemoryDlg(_hInstance, hwndMain, currentDebugMIPS));
DialogManager::AddDlg(vfpudlg = new CVFPUDlg(_hInstance, hwndMain, currentDebugMIPS));
MainWindow::Update();
MainWindow::UpdateMenus();
LogManager::Init();
LogManager::GetInstance()->GetConsoleListener()->Open(hideLog, 150, 120, "PPSSPP Debug Console");
LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LERROR);
host = new WindowsHost(hwndMain, hwndDisplay);
// Emu thread is always running!
EmuThread_Start();
if (g_Config.bBrowse)
MainWindow::BrowseAndBoot("");
if (!hideLog)
SetForegroundWindow(hwndMain);
HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS);
//so.. we're at the message pump of the GUI thread
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) //while no quit
for (MSG msg; GetMessage(&msg, NULL, 0, 0); ) // for no quit
{
//DSound_UpdateSound();