mirror of https://github.com/PCSX2/pcsx2.git
Common: Remove Exceptions
The satisfaction is immeasurable.
This commit is contained in:
parent
2ae78f6e2f
commit
6beaec8ba1
|
@ -0,0 +1,133 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 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 for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Threading.h"
|
||||||
|
#include "General.h"
|
||||||
|
#include "Assertions.h"
|
||||||
|
#include "CrashHandler.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include "fmt/core.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "RedtapeWindows.h"
|
||||||
|
#include <intrin.h>
|
||||||
|
#include <tlhelp32.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __UNIX__
|
||||||
|
#include <signal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static std::mutex s_assertion_failed_mutex;
|
||||||
|
|
||||||
|
static inline void FreezeThreads(void** handle)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||||
|
if (snapshot != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
THREADENTRY32 threadEntry;
|
||||||
|
if (Thread32First(snapshot, &threadEntry))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (threadEntry.th32ThreadID == GetCurrentThreadId())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadEntry.th32ThreadID);
|
||||||
|
if (hThread != nullptr)
|
||||||
|
{
|
||||||
|
SuspendThread(hThread);
|
||||||
|
CloseHandle(hThread);
|
||||||
|
}
|
||||||
|
} while (Thread32Next(snapshot, &threadEntry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*handle = static_cast<void*>(snapshot);
|
||||||
|
#else
|
||||||
|
* handle = nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ResumeThreads(void* handle)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
THREADENTRY32 threadEntry;
|
||||||
|
if (Thread32First(reinterpret_cast<HANDLE>(handle), &threadEntry))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (threadEntry.th32ThreadID == GetCurrentThreadId())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadEntry.th32ThreadID);
|
||||||
|
if (hThread != nullptr)
|
||||||
|
{
|
||||||
|
ResumeThread(hThread);
|
||||||
|
CloseHandle(hThread);
|
||||||
|
}
|
||||||
|
} while (Thread32Next(reinterpret_cast<HANDLE>(handle), &threadEntry));
|
||||||
|
}
|
||||||
|
CloseHandle(reinterpret_cast<HANDLE>(handle));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void pxOnAssertFail(const char* file, int line, const char* func, const char* msg)
|
||||||
|
{
|
||||||
|
std::unique_lock guard(s_assertion_failed_mutex);
|
||||||
|
|
||||||
|
void* handle;
|
||||||
|
FreezeThreads(&handle);
|
||||||
|
|
||||||
|
char full_msg[512];
|
||||||
|
std::snprintf(full_msg, sizeof(full_msg), "%s:%d: assertion failed in function %s: %s\n", file, line, func, msg);
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
HANDLE error_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
if (error_handle != INVALID_HANDLE_VALUE)
|
||||||
|
WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), full_msg, static_cast<DWORD>(std::strlen(full_msg)), NULL, NULL);
|
||||||
|
OutputDebugStringA(full_msg);
|
||||||
|
|
||||||
|
std::snprintf(
|
||||||
|
full_msg, sizeof(full_msg),
|
||||||
|
"Assertion failed in function %s (%s:%d):\n\n%s\n\nPress Abort to exit, Retry to break to debugger, or Ignore to attempt to continue.",
|
||||||
|
func, file, line, msg);
|
||||||
|
|
||||||
|
int result = MessageBoxA(NULL, full_msg, NULL, MB_ABORTRETRYIGNORE | MB_ICONERROR);
|
||||||
|
if (result == IDRETRY)
|
||||||
|
{
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
else if (result != IDIGNORE)
|
||||||
|
{
|
||||||
|
// try to save a crash dump before exiting
|
||||||
|
CrashHandler::WriteDumpForCaller();
|
||||||
|
TerminateProcess(GetCurrentProcess(), 0xBAADC0DE);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
fputs(full_msg, stderr);
|
||||||
|
fputs("\nAborting application.\n", stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
AbortWithMessage(full_msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ResumeThreads(handle);
|
||||||
|
}
|
|
@ -10,12 +10,12 @@ add_library(common)
|
||||||
# x86emitter sources
|
# x86emitter sources
|
||||||
target_sources(common PRIVATE
|
target_sources(common PRIVATE
|
||||||
AlignedMalloc.cpp
|
AlignedMalloc.cpp
|
||||||
|
Assertions.cpp
|
||||||
SafeArray.inl
|
SafeArray.inl
|
||||||
Console.cpp
|
Console.cpp
|
||||||
CrashHandler.cpp
|
CrashHandler.cpp
|
||||||
DynamicLibrary.cpp
|
DynamicLibrary.cpp
|
||||||
Error.cpp
|
Error.cpp
|
||||||
Exceptions.cpp
|
|
||||||
FastJmp.cpp
|
FastJmp.cpp
|
||||||
FileSystem.cpp
|
FileSystem.cpp
|
||||||
General.cpp
|
General.cpp
|
||||||
|
@ -72,7 +72,6 @@ target_sources(common PRIVATE
|
||||||
Easing.h
|
Easing.h
|
||||||
EnumOps.h
|
EnumOps.h
|
||||||
Error.h
|
Error.h
|
||||||
Exceptions.h
|
|
||||||
FastJmp.h
|
FastJmp.h
|
||||||
FileSystem.h
|
FileSystem.h
|
||||||
General.h
|
General.h
|
||||||
|
|
|
@ -1,346 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
|
||||||
*
|
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
||||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
||||||
* ation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* PCSX2 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 for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Threading.h"
|
|
||||||
#include "General.h"
|
|
||||||
#include "Exceptions.h"
|
|
||||||
#include "CrashHandler.h"
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include "fmt/core.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include "RedtapeWindows.h"
|
|
||||||
#include <intrin.h>
|
|
||||||
#include <tlhelp32.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __UNIX__
|
|
||||||
#include <signal.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static std::mutex s_assertion_failed_mutex;
|
|
||||||
|
|
||||||
static inline void FreezeThreads(void** handle)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
|
||||||
if (snapshot != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
THREADENTRY32 threadEntry;
|
|
||||||
if (Thread32First(snapshot, &threadEntry))
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (threadEntry.th32ThreadID == GetCurrentThreadId())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadEntry.th32ThreadID);
|
|
||||||
if (hThread != nullptr)
|
|
||||||
{
|
|
||||||
SuspendThread(hThread);
|
|
||||||
CloseHandle(hThread);
|
|
||||||
}
|
|
||||||
} while (Thread32Next(snapshot, &threadEntry));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*handle = static_cast<void*>(snapshot);
|
|
||||||
#else
|
|
||||||
* handle = nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ResumeThreads(void* handle)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
if (handle != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
THREADENTRY32 threadEntry;
|
|
||||||
if (Thread32First(reinterpret_cast<HANDLE>(handle), &threadEntry))
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (threadEntry.th32ThreadID == GetCurrentThreadId())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadEntry.th32ThreadID);
|
|
||||||
if (hThread != nullptr)
|
|
||||||
{
|
|
||||||
ResumeThread(hThread);
|
|
||||||
CloseHandle(hThread);
|
|
||||||
}
|
|
||||||
} while (Thread32Next(reinterpret_cast<HANDLE>(handle), &threadEntry));
|
|
||||||
}
|
|
||||||
CloseHandle(reinterpret_cast<HANDLE>(handle));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void pxOnAssertFail(const char* file, int line, const char* func, const char* msg)
|
|
||||||
{
|
|
||||||
std::unique_lock guard(s_assertion_failed_mutex);
|
|
||||||
|
|
||||||
void* handle;
|
|
||||||
FreezeThreads(&handle);
|
|
||||||
|
|
||||||
char full_msg[512];
|
|
||||||
std::snprintf(full_msg, sizeof(full_msg), "%s:%d: assertion failed in function %s: %s\n", file, line, func, msg);
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
HANDLE error_handle = GetStdHandle(STD_ERROR_HANDLE);
|
|
||||||
if (error_handle != INVALID_HANDLE_VALUE)
|
|
||||||
WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), full_msg, static_cast<DWORD>(std::strlen(full_msg)), NULL, NULL);
|
|
||||||
OutputDebugStringA(full_msg);
|
|
||||||
|
|
||||||
std::snprintf(
|
|
||||||
full_msg, sizeof(full_msg),
|
|
||||||
"Assertion failed in function %s (%s:%d):\n\n%s\n\nPress Abort to exit, Retry to break to debugger, or Ignore to attempt to continue.",
|
|
||||||
func, file, line, msg);
|
|
||||||
|
|
||||||
int result = MessageBoxA(NULL, full_msg, NULL, MB_ABORTRETRYIGNORE | MB_ICONERROR);
|
|
||||||
if (result == IDRETRY)
|
|
||||||
{
|
|
||||||
__debugbreak();
|
|
||||||
}
|
|
||||||
else if (result != IDIGNORE)
|
|
||||||
{
|
|
||||||
// try to save a crash dump before exiting
|
|
||||||
CrashHandler::WriteDumpForCaller();
|
|
||||||
TerminateProcess(GetCurrentProcess(), 0xBAADC0DE);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
fputs(full_msg, stderr);
|
|
||||||
fputs("\nAborting application.\n", stderr);
|
|
||||||
fflush(stderr);
|
|
||||||
AbortWithMessage(full_msg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ResumeThreads(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// BaseException (implementations)
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
BaseException& BaseException::SetBothMsgs(const char* msg_diag)
|
|
||||||
{
|
|
||||||
m_message_user = msg_diag ? std::string(msg_diag) : std::string();
|
|
||||||
return SetDiagMsg(msg_diag);
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseException& BaseException::SetDiagMsg(std::string msg_diag)
|
|
||||||
{
|
|
||||||
m_message_diag = std::move(msg_diag);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseException& BaseException::SetUserMsg(std::string msg_user)
|
|
||||||
{
|
|
||||||
m_message_user = std::move(msg_user);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string BaseException::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
return m_message_diag;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string BaseException::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
return m_message_user.empty() ? m_message_diag : m_message_user;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// Exception::RuntimeError (implementations)
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
Exception::RuntimeError::RuntimeError(const std::runtime_error& ex, const char* prefix /* = nullptr */)
|
|
||||||
{
|
|
||||||
IsSilent = false;
|
|
||||||
|
|
||||||
const bool has_prefix = prefix && prefix[0] != 0;
|
|
||||||
|
|
||||||
SetDiagMsg(fmt::format("STL Runtime Error{}{}{}: {}",
|
|
||||||
has_prefix ? " (" : "", prefix ? prefix : "", has_prefix ? ")" : "",
|
|
||||||
ex.what()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Exception::RuntimeError::RuntimeError(const std::exception& ex, const char* prefix /* = nullptr */)
|
|
||||||
{
|
|
||||||
IsSilent = false;
|
|
||||||
|
|
||||||
const bool has_prefix = prefix && prefix[0] != 0;
|
|
||||||
|
|
||||||
SetDiagMsg(fmt::format("STL Exception{}{}{}: {}",
|
|
||||||
has_prefix ? " (" : "", prefix ? prefix : "", has_prefix ? ")" : "",
|
|
||||||
ex.what()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// Exception::BadStream (implementations)
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
std::string Exception::BadStream::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
_formatDiagMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Exception::BadStream::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
_formatUserMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Exception::BadStream::_formatDiagMsg(std::string& dest) const
|
|
||||||
{
|
|
||||||
fmt::format_to(std::back_inserter(dest), "Path: ");
|
|
||||||
if (!StreamName.empty())
|
|
||||||
fmt::format_to(std::back_inserter(dest), "{}", StreamName);
|
|
||||||
else
|
|
||||||
dest += "[Unnamed or unknown]";
|
|
||||||
|
|
||||||
if (!m_message_diag.empty())
|
|
||||||
fmt::format_to(std::back_inserter(dest), "\n{}", m_message_diag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Exception::BadStream::_formatUserMsg(std::string& dest) const
|
|
||||||
{
|
|
||||||
fmt::format_to(std::back_inserter(dest), "Path: ");
|
|
||||||
if (!StreamName.empty())
|
|
||||||
fmt::format_to(std::back_inserter(dest), "{}", StreamName);
|
|
||||||
else
|
|
||||||
dest += "[Unnamed or unknown]";
|
|
||||||
|
|
||||||
if (!m_message_user.empty())
|
|
||||||
fmt::format_to(std::back_inserter(dest), "\n{}", m_message_user);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// Exception::CannotCreateStream (implementations)
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
std::string Exception::CannotCreateStream::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
retval = "File could not be created.";
|
|
||||||
_formatDiagMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Exception::CannotCreateStream::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
retval = "A file could not be created.\n";
|
|
||||||
_formatUserMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// Exception::FileNotFound (implementations)
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
std::string Exception::FileNotFound::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
retval = "File not found.\n";
|
|
||||||
_formatDiagMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Exception::FileNotFound::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
retval = "File not found.\n";
|
|
||||||
_formatUserMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// Exception::AccessDenied (implementations)
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
std::string Exception::AccessDenied::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
retval = "Permission denied to file.\n";
|
|
||||||
_formatDiagMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Exception::AccessDenied::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
retval = "Permission denied while trying to open file, likely due to insufficient user account rights.\n";
|
|
||||||
_formatUserMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// Exception::EndOfStream (implementations)
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
std::string Exception::EndOfStream::FormatDiagnosticMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
retval = "Unexpected end of file or stream.\n";
|
|
||||||
_formatDiagMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Exception::EndOfStream::FormatDisplayMessage() const
|
|
||||||
{
|
|
||||||
std::string retval;
|
|
||||||
retval = "Unexpected end of file or stream encountered. File is probably truncated or corrupted.\n";
|
|
||||||
_formatUserMsg(retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// Exceptions from Errno (POSIX)
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Translates an Errno code into an exception.
|
|
||||||
// Throws an exception based on the given error code (usually taken from ANSI C's errno)
|
|
||||||
std::unique_ptr<BaseException> Exception::FromErrno(std::string streamname, int errcode)
|
|
||||||
{
|
|
||||||
pxAssumeDev(errcode != 0, "Invalid NULL error code? (errno)");
|
|
||||||
|
|
||||||
switch (errcode)
|
|
||||||
{
|
|
||||||
case EINVAL:
|
|
||||||
pxFailDev("Invalid argument");
|
|
||||||
return std::unique_ptr<BaseException>(&(new Exception::BadStream(streamname))->SetDiagMsg("Invalid argument? (likely caused by an unforgivable programmer error!)"));
|
|
||||||
|
|
||||||
case EACCES: // Access denied!
|
|
||||||
return std::unique_ptr<BaseException>(new Exception::AccessDenied(streamname));
|
|
||||||
|
|
||||||
case EMFILE: // Too many open files!
|
|
||||||
return std::unique_ptr<BaseException>(&(new Exception::CannotCreateStream(streamname))->SetDiagMsg("Too many open files")); // File handle allocation failure
|
|
||||||
|
|
||||||
case EEXIST:
|
|
||||||
return std::unique_ptr<BaseException>(&(new Exception::CannotCreateStream(streamname))->SetDiagMsg("File already exists"));
|
|
||||||
|
|
||||||
case ENOENT: // File not found!
|
|
||||||
return std::unique_ptr<BaseException>(new Exception::FileNotFound(streamname));
|
|
||||||
|
|
||||||
case EPIPE:
|
|
||||||
return std::unique_ptr<BaseException>(&(new Exception::BadStream(streamname))->SetDiagMsg("Broken pipe"));
|
|
||||||
|
|
||||||
case EBADF:
|
|
||||||
return std::unique_ptr<BaseException>(&(new Exception::BadStream(streamname))->SetDiagMsg("Bad file number"));
|
|
||||||
|
|
||||||
default:
|
|
||||||
return std::unique_ptr<BaseException>(&(new Exception::BadStream(streamname))->SetDiagMsg(fmt::format("General file/stream error [errno: {}]", errcode)));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,255 +0,0 @@
|
||||||
/* PCSX2 - PS2 Emulator for PCs
|
|
||||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
|
||||||
*
|
|
||||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
||||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
||||||
* ation, either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* PCSX2 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 for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include "common/Assertions.h"
|
|
||||||
#include "common/Pcsx2Defs.h"
|
|
||||||
|
|
||||||
namespace Exception
|
|
||||||
{
|
|
||||||
class BaseException;
|
|
||||||
|
|
||||||
std::unique_ptr<BaseException> FromErrno(std::string streamname, int errcode);
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// BaseException
|
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// std::exception sucks, and isn't entirely cross-platform reliable in its implementation,
|
|
||||||
// so I made a replacement. The internal messages are non-const, which means that a
|
|
||||||
// catch clause can optionally modify them and then re-throw to a top-level handler.
|
|
||||||
//
|
|
||||||
// Note, this class is "abstract" which means you shouldn't use it directly like, ever.
|
|
||||||
// Use Exception::RuntimeError instead for generic exceptions.
|
|
||||||
//
|
|
||||||
// Because exceptions are the (only!) really useful example of multiple inheritance,
|
|
||||||
// this class has only a trivial constructor, and must be manually initialized using
|
|
||||||
// InitBaseEx() or by individual member assignments. This is because C++ multiple inheritence
|
|
||||||
// is, by design, a lot of fail, especially when class initializers are mixed in.
|
|
||||||
//
|
|
||||||
// [TODO] : Add an InnerException component, and Clone() facility.
|
|
||||||
//
|
|
||||||
class BaseException
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
std::string m_message_diag; // (untranslated) a "detailed" message of what disastrous thing has occurred!
|
|
||||||
std::string m_message_user; // (translated) a "detailed" message of what disastrous thing has occurred!
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~BaseException() = default;
|
|
||||||
|
|
||||||
const std::string& DiagMsg() const { return m_message_diag; }
|
|
||||||
const std::string& UserMsg() const { return m_message_user; }
|
|
||||||
|
|
||||||
std::string& DiagMsg() { return m_message_diag; }
|
|
||||||
std::string& UserMsg() { return m_message_user; }
|
|
||||||
|
|
||||||
BaseException& SetBothMsgs(const char* msg_diag);
|
|
||||||
BaseException& SetDiagMsg(std::string msg_diag);
|
|
||||||
BaseException& SetUserMsg(std::string msg_user);
|
|
||||||
|
|
||||||
// Returns a message suitable for diagnostic / logging purposes.
|
|
||||||
// This message is always in English, and includes a full stack trace.
|
|
||||||
virtual std::string FormatDiagnosticMessage() const;
|
|
||||||
|
|
||||||
// Returns a message suitable for end-user display.
|
|
||||||
// This message is usually meant for display in a user popup or such.
|
|
||||||
virtual std::string FormatDisplayMessage() const;
|
|
||||||
|
|
||||||
virtual void Rethrow() const = 0;
|
|
||||||
virtual BaseException* Clone() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Some helper macros for defining the standard constructors of internationalized constructors
|
|
||||||
// Parameters:
|
|
||||||
// classname - Yeah, the name of this class being defined. :)
|
|
||||||
//
|
|
||||||
// defmsg - default message (in english), which will be used for both english and i18n messages.
|
|
||||||
// The text string will be passed through the translator, so if it's int he gettext database
|
|
||||||
// it will be optionally translated.
|
|
||||||
//
|
|
||||||
// BUGZ?? I'd rather use 'classname' on the Clone() prototype, but for some reason it generates
|
|
||||||
// ambiguity errors on virtual inheritance (it really shouldn't!). So I have to force it to the
|
|
||||||
// BaseException base class. Not sure if this is Stupid Standard Tricks or Stupid MSVC Tricks. --air
|
|
||||||
//
|
|
||||||
// (update: web searches indicate it's MSVC specific -- happens in 2008, not sure about 2010).
|
|
||||||
//
|
|
||||||
#define DEFINE_EXCEPTION_COPYTORS(classname, parent) \
|
|
||||||
private: \
|
|
||||||
typedef parent _parent; \
|
|
||||||
\
|
|
||||||
public: \
|
|
||||||
virtual ~classname() = default; \
|
|
||||||
\
|
|
||||||
virtual void Rethrow() const override \
|
|
||||||
{ \
|
|
||||||
throw *this; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
virtual classname* Clone() const override \
|
|
||||||
{ \
|
|
||||||
return new classname(*this); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_EXCEPTION_MESSAGES(classname) \
|
|
||||||
public: \
|
|
||||||
classname& SetBothMsgs(const char* msg_diag) \
|
|
||||||
{ \
|
|
||||||
BaseException::SetBothMsgs(msg_diag); \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
classname& SetDiagMsg(std::string msg_diag) \
|
|
||||||
{ \
|
|
||||||
m_message_diag = msg_diag; \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
classname& SetUserMsg(std::string msg_user) \
|
|
||||||
{ \
|
|
||||||
m_message_user = std::move(msg_user); \
|
|
||||||
return *this; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFINE_RUNTIME_EXCEPTION(classname, parent, message) \
|
|
||||||
DEFINE_EXCEPTION_COPYTORS(classname, parent) \
|
|
||||||
classname() \
|
|
||||||
{ \
|
|
||||||
SetDiagMsg(message); \
|
|
||||||
} \
|
|
||||||
DEFINE_EXCEPTION_MESSAGES(classname)
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
// RuntimeError - Generalized Exceptions with Recoverable Traits!
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class RuntimeError : public BaseException
|
|
||||||
{
|
|
||||||
DEFINE_EXCEPTION_COPYTORS(RuntimeError, BaseException)
|
|
||||||
DEFINE_EXCEPTION_MESSAGES(RuntimeError)
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool IsSilent;
|
|
||||||
|
|
||||||
RuntimeError() { IsSilent = false; }
|
|
||||||
RuntimeError(const std::runtime_error& ex, const char* prefix = nullptr);
|
|
||||||
RuntimeError(const std::exception& ex, const char* prefix = nullptr);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
// Streaming (file) Exceptions:
|
|
||||||
// Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#define DEFINE_STREAM_EXCEPTION(classname, parent) \
|
|
||||||
DEFINE_RUNTIME_EXCEPTION(classname, parent, "") \
|
|
||||||
classname(std::string filename) \
|
|
||||||
{ \
|
|
||||||
StreamName = filename; \
|
|
||||||
} \
|
|
||||||
virtual classname& SetStreamName(std::string name) override \
|
|
||||||
{ \
|
|
||||||
StreamName = std::move(name); \
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
virtual classname& SetStreamName(const char* name) override \
|
|
||||||
{ \
|
|
||||||
StreamName = name; \
|
|
||||||
return *this; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// A generic base error class for bad streams -- corrupted data, sudden closures, loss of
|
|
||||||
// connection, or anything else that would indicate a failure to open a stream or read the
|
|
||||||
// data after the stream was successfully opened.
|
|
||||||
//
|
|
||||||
class BadStream : public RuntimeError
|
|
||||||
{
|
|
||||||
DEFINE_RUNTIME_EXCEPTION(BadStream, RuntimeError, "")
|
|
||||||
|
|
||||||
public:
|
|
||||||
BadStream(std::string filename)
|
|
||||||
: StreamName(std::move(filename))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
virtual BadStream& SetStreamName(std::string name)
|
|
||||||
{
|
|
||||||
StreamName = std::move(name);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
virtual BadStream& SetStreamName(const char* name)
|
|
||||||
{
|
|
||||||
StreamName = name;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string StreamName; // name of the stream (if applicable)
|
|
||||||
|
|
||||||
virtual std::string FormatDiagnosticMessage() const override;
|
|
||||||
virtual std::string FormatDisplayMessage() const override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void _formatDiagMsg(std::string& dest) const;
|
|
||||||
void _formatUserMsg(std::string& dest) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A generic exception for odd-ball stream creation errors.
|
|
||||||
//
|
|
||||||
class CannotCreateStream : public BadStream
|
|
||||||
{
|
|
||||||
DEFINE_STREAM_EXCEPTION(CannotCreateStream, BadStream)
|
|
||||||
|
|
||||||
virtual std::string FormatDiagnosticMessage() const override;
|
|
||||||
virtual std::string FormatDisplayMessage() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Exception thrown when an attempt to open a non-existent file is made.
|
|
||||||
// (this exception can also mean file permissions are invalid)
|
|
||||||
//
|
|
||||||
class FileNotFound : public CannotCreateStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DEFINE_STREAM_EXCEPTION(FileNotFound, CannotCreateStream)
|
|
||||||
|
|
||||||
virtual std::string FormatDiagnosticMessage() const override;
|
|
||||||
virtual std::string FormatDisplayMessage() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AccessDenied : public CannotCreateStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DEFINE_STREAM_EXCEPTION(AccessDenied, CannotCreateStream)
|
|
||||||
|
|
||||||
virtual std::string FormatDiagnosticMessage() const override;
|
|
||||||
virtual std::string FormatDisplayMessage() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
// EndOfStream can be used either as an error, or used just as a shortcut for manual
|
|
||||||
// feof checks.
|
|
||||||
//
|
|
||||||
class EndOfStream : public BadStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DEFINE_STREAM_EXCEPTION(EndOfStream, BadStream)
|
|
||||||
|
|
||||||
virtual std::string FormatDiagnosticMessage() const override;
|
|
||||||
virtual std::string FormatDisplayMessage() const override;
|
|
||||||
};
|
|
||||||
} // namespace Exception
|
|
||||||
|
|
||||||
using Exception::BaseException;
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "common/RedtapeWindows.h"
|
#include "common/RedtapeWindows.h"
|
||||||
#include "common/Console.h"
|
#include "common/Console.h"
|
||||||
#include "common/General.h"
|
#include "common/General.h"
|
||||||
#include "common/Exceptions.h"
|
|
||||||
#include "common/StringUtil.h"
|
#include "common/StringUtil.h"
|
||||||
#include "common/AlignedMalloc.h"
|
#include "common/AlignedMalloc.h"
|
||||||
#include "common/Assertions.h"
|
#include "common/Assertions.h"
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include "common/Pcsx2Defs.h"
|
#include "common/Pcsx2Defs.h"
|
||||||
#include "common/RedtapeWindows.h"
|
#include "common/RedtapeWindows.h"
|
||||||
#include "common/Exceptions.h"
|
|
||||||
#include "common/StringUtil.h"
|
#include "common/StringUtil.h"
|
||||||
#include "common/Threading.h"
|
#include "common/Threading.h"
|
||||||
#include "common/General.h"
|
#include "common/General.h"
|
||||||
|
|
|
@ -46,11 +46,11 @@
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="AlignedMalloc.cpp" />
|
<ClCompile Include="AlignedMalloc.cpp" />
|
||||||
|
<ClCompile Include="Assertions.cpp" />
|
||||||
<ClCompile Include="Console.cpp" />
|
<ClCompile Include="Console.cpp" />
|
||||||
<ClCompile Include="CrashHandler.cpp" />
|
<ClCompile Include="CrashHandler.cpp" />
|
||||||
<ClCompile Include="DynamicLibrary.cpp" />
|
<ClCompile Include="DynamicLibrary.cpp" />
|
||||||
<ClCompile Include="Error.cpp" />
|
<ClCompile Include="Error.cpp" />
|
||||||
<ClCompile Include="Exceptions.cpp" />
|
|
||||||
<ClCompile Include="FastJmp.cpp">
|
<ClCompile Include="FastJmp.cpp">
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -133,7 +133,6 @@
|
||||||
<ClInclude Include="SettingsWrapper.h" />
|
<ClInclude Include="SettingsWrapper.h" />
|
||||||
<ClInclude Include="Assertions.h" />
|
<ClInclude Include="Assertions.h" />
|
||||||
<ClInclude Include="Console.h" />
|
<ClInclude Include="Console.h" />
|
||||||
<ClInclude Include="Exceptions.h" />
|
|
||||||
<ClInclude Include="General.h" />
|
<ClInclude Include="General.h" />
|
||||||
<ClInclude Include="MathUtils.h" />
|
<ClInclude Include="MathUtils.h" />
|
||||||
<ClInclude Include="Path.h" />
|
<ClInclude Include="Path.h" />
|
||||||
|
|
|
@ -13,9 +13,6 @@
|
||||||
<ClCompile Include="emitter\cpudetect.cpp">
|
<ClCompile Include="emitter\cpudetect.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Exceptions.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="emitter\fpu.cpp">
|
<ClCompile Include="emitter\fpu.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -142,6 +139,9 @@
|
||||||
<ClCompile Include="Error.cpp">
|
<ClCompile Include="Error.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Assertions.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="AlignedMalloc.h">
|
<ClInclude Include="AlignedMalloc.h">
|
||||||
|
@ -162,9 +162,6 @@
|
||||||
<ClInclude Include="emitter\implement\dwshift.h">
|
<ClInclude Include="emitter\implement\dwshift.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Exceptions.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="General.h">
|
<ClInclude Include="General.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
#include "common/Assertions.h"
|
#include "common/Assertions.h"
|
||||||
#include "common/Console.h"
|
#include "common/Console.h"
|
||||||
#include "common/Exceptions.h"
|
|
||||||
#include "common/FileSystem.h"
|
#include "common/FileSystem.h"
|
||||||
#include "common/MemorySettingsInterface.h"
|
#include "common/MemorySettingsInterface.h"
|
||||||
#include "common/Path.h"
|
#include "common/Path.h"
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
#include "common/Assertions.h"
|
#include "common/Assertions.h"
|
||||||
#include "common/Console.h"
|
#include "common/Console.h"
|
||||||
#include "common/CrashHandler.h"
|
#include "common/CrashHandler.h"
|
||||||
#include "common/Exceptions.h"
|
|
||||||
#include "common/FileSystem.h"
|
#include "common/FileSystem.h"
|
||||||
#include "common/Path.h"
|
#include "common/Path.h"
|
||||||
#include "common/SettingsWrapper.h"
|
#include "common/SettingsWrapper.h"
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include "IsoFileFormats.h"
|
#include "IsoFileFormats.h"
|
||||||
|
|
||||||
#include "common/Assertions.h"
|
#include "common/Assertions.h"
|
||||||
#include "common/Exceptions.h"
|
|
||||||
#include "common/FileSystem.h"
|
#include "common/FileSystem.h"
|
||||||
#include "common/Path.h"
|
#include "common/Path.h"
|
||||||
#include "common/StringUtil.h"
|
#include "common/StringUtil.h"
|
||||||
|
|
|
@ -24,7 +24,8 @@
|
||||||
#include "IsoFileFormats.h"
|
#include "IsoFileFormats.h"
|
||||||
#include "AsyncFileReader.h"
|
#include "AsyncFileReader.h"
|
||||||
#include "CDVD/CDVD.h"
|
#include "CDVD/CDVD.h"
|
||||||
#include "common/Exceptions.h"
|
|
||||||
|
#include "common/Assertions.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "CDVD/IsoFileFormats.h"
|
#include "CDVD/IsoFileFormats.h"
|
||||||
#include "Host.h"
|
#include "Host.h"
|
||||||
|
|
||||||
#include "common/Exceptions.h"
|
|
||||||
#include "common/FileSystem.h"
|
#include "common/FileSystem.h"
|
||||||
#include "common/StringUtil.h"
|
#include "common/StringUtil.h"
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include "SysForwardDefs.h"
|
#include "SysForwardDefs.h"
|
||||||
|
|
||||||
#include "common/Exceptions.h"
|
|
||||||
#include "common/SafeArray.h"
|
#include "common/SafeArray.h"
|
||||||
#include "common/Threading.h"
|
#include "common/Threading.h"
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
#include "VUops.h"
|
#include "VUops.h"
|
||||||
#include "R5900.h"
|
#include "R5900.h"
|
||||||
|
|
||||||
#include "common/Exceptions.h"
|
|
||||||
|
|
||||||
static const uint VU0_MEMSIZE = 0x1000; // 4kb
|
static const uint VU0_MEMSIZE = 0x1000; // 4kb
|
||||||
static const uint VU0_PROGSIZE = 0x1000; // 4kb
|
static const uint VU0_PROGSIZE = 0x1000; // 4kb
|
||||||
static const uint VU1_MEMSIZE = 0x4000; // 16kb
|
static const uint VU1_MEMSIZE = 0x4000; // 16kb
|
||||||
|
|
Loading…
Reference in New Issue