fix shared memory reboot loss

This commit is contained in:
RadWolfie 2019-10-18 11:10:48 -05:00
parent 7fca148bc6
commit b20a970b1d
2 changed files with 65 additions and 44 deletions

View File

@ -577,6 +577,26 @@ XBSYSAPI EXPORTNUM(49) xboxkrnl::VOID DECLSPEC_NORETURN NTAPI xboxkrnl::HalRetur
if (!CxbxExec(false, nullptr, false)) { if (!CxbxExec(false, nullptr, false)) {
CxbxKrnlCleanup("Could not launch %s", XbePath.c_str()); CxbxKrnlCleanup("Could not launch %s", XbePath.c_str());
} }
// This is a requirement to have shared memory buffers remain alive and transfer to new emulation process.
unsigned int retryAttempt = 0;
unsigned int curProcID = 0;
unsigned int oldProcID = GetCurrentProcessId();
while(true) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
g_EmuShared->GetKrnlProcID(&curProcID);
// Break when new emulation process has take over.
if (curProcID != oldProcID) {
break;
}
retryAttempt++;
// Terminate after 5 seconds of failure.
if (retryAttempt >= (5 * (1000 / 100))) {
CxbxShowError("Could not reboot, new emulation process did not take over.");
break;
}
}
} }
} }
break; break;

View File

@ -752,11 +752,6 @@ void CxbxKrnlEmulate(uint32_t blocks_reserved[384])
/* Initialize Cxbx File Paths */ /* Initialize Cxbx File Paths */
CxbxInitFilePaths(); CxbxInitFilePaths();
/* Must be called after CxbxInitFilePaths */
if (!CxbxLockFilePath()) {
return;
}
// Skip '/load' switch // Skip '/load' switch
// Get XBE Name : // Get XBE Name :
std::string xbePath; std::string xbePath;
@ -784,44 +779,8 @@ void CxbxKrnlEmulate(uint32_t blocks_reserved[384])
} }
int BootFlags; int BootFlags;
FILE* krnlLog = nullptr;
g_EmuShared->GetBootFlags(&BootFlags); g_EmuShared->GetBootFlags(&BootFlags);
// debug console allocation (if configured)
if (DbgMode == DM_CONSOLE)
{
if (AllocConsole())
{
HANDLE StdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
// Maximise the console scroll buffer height :
CONSOLE_SCREEN_BUFFER_INFO coninfo;
GetConsoleScreenBufferInfo(StdHandle, &coninfo);
coninfo.dwSize.Y = SHRT_MAX - 1; // = 32767-1 = 32766 = maximum value that works
SetConsoleScreenBufferSize(StdHandle, coninfo.dwSize);
(void)freopen("CONOUT$", "wt", stdout);
(void)freopen("CONIN$", "rt", stdin);
SetConsoleTitle("Cxbx-Reloaded : Kernel Debug Console");
SetConsoleTextAttribute(StdHandle, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
}
}
else
{
FreeConsole();
if (DbgMode == DM_FILE) {
// Peform clean write to kernel log for first boot. Unless multi-xbe boot occur then perform append to existing log.
krnlLog = freopen(DebugFileName.c_str(), ((BootFlags == DebugMode::DM_NONE) ? "wt" : "at"), stdout);
// Append separator for better readability after reboot.
if (BootFlags != DebugMode::DM_NONE) {
std::cout << "\n------REBOOT------REBOOT------REBOOT------REBOOT------REBOOT------\n" << std::endl;
}
}
else {
char buffer[16];
if (GetConsoleTitle(buffer, 16) != NULL)
(void)freopen("nul", "w", stdout);
}
}
g_CurrentProcessHandle = GetCurrentProcess(); // OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); g_CurrentProcessHandle = GetCurrentProcess(); // OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
// Set up the logging variables for the kernel process during initialization. // Set up the logging variables for the kernel process during initialization.
@ -862,6 +821,10 @@ void CxbxKrnlEmulate(uint32_t blocks_reserved[384])
DWORD dwExitCode = EXIT_SUCCESS; DWORD dwExitCode = EXIT_SUCCESS;
g_EmuShared->GetKrnlProcID(&prevKrnlProcID); g_EmuShared->GetKrnlProcID(&prevKrnlProcID);
// Save current kernel proccess id for next reboot if will occur in the future.
// And to tell previous kernel process we had take over. This allow reboot's shared memory buffer to survive.
g_EmuShared->SetKrnlProcID(GetCurrentProcessId());
// Force wait until previous kernel process is closed. // Force wait until previous kernel process is closed.
if (prevKrnlProcID != 0) { if (prevKrnlProcID != 0) {
HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, prevKrnlProcID); HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, prevKrnlProcID);
@ -879,15 +842,53 @@ void CxbxKrnlEmulate(uint32_t blocks_reserved[384])
CxbxKrnlShutDown(); CxbxKrnlShutDown();
} }
/* Must be called after CxbxInitFilePaths and previous kernel process shutdown. */
if (!CxbxLockFilePath()) {
return;
}
FILE* krnlLog = nullptr;
// debug console allocation (if configured)
if (DbgMode == DM_CONSOLE)
{
if (AllocConsole())
{
HANDLE StdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
// Maximise the console scroll buffer height :
CONSOLE_SCREEN_BUFFER_INFO coninfo;
GetConsoleScreenBufferInfo(StdHandle, &coninfo);
coninfo.dwSize.Y = SHRT_MAX - 1; // = 32767-1 = 32766 = maximum value that works
SetConsoleScreenBufferSize(StdHandle, coninfo.dwSize);
(void)freopen("CONOUT$", "wt", stdout);
(void)freopen("CONIN$", "rt", stdin);
SetConsoleTitle("Cxbx-Reloaded : Kernel Debug Console");
SetConsoleTextAttribute(StdHandle, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
}
}
else
{
FreeConsole();
if (DbgMode == DM_FILE) {
// Peform clean write to kernel log for first boot. Unless multi-xbe boot occur then perform append to existing log.
krnlLog = freopen(DebugFileName.c_str(), ((BootFlags == DebugMode::DM_NONE) ? "wt" : "at"), stdout);
// Append separator for better readability after reboot.
if (BootFlags != DebugMode::DM_NONE) {
std::cout << "\n------REBOOT------REBOOT------REBOOT------REBOOT------REBOOT------\n" << std::endl;
}
}
else {
char buffer[16];
if (GetConsoleTitle(buffer, 16) != NULL)
(void)freopen("nul", "w", stdout);
}
}
bool isLogEnabled; bool isLogEnabled;
g_EmuShared->GetIsKrnlLogEnabled(&isLogEnabled); g_EmuShared->GetIsKrnlLogEnabled(&isLogEnabled);
g_bPrintfOn = isLogEnabled; g_bPrintfOn = isLogEnabled;
g_EmuShared->ResetKrnl(); g_EmuShared->ResetKrnl();
// Save current kernel proccess id for next reboot if will occur in the future.
g_EmuShared->SetKrnlProcID(GetCurrentProcessId());
// Write a header to the log // Write a header to the log
{ {
EmuLogInit(LOG_LEVEL::INFO, "Cxbx-Reloaded Version %s", CxbxVersionStr); EmuLogInit(LOG_LEVEL::INFO, "Cxbx-Reloaded Version %s", CxbxVersionStr);