Skip to content

Commit

Permalink
exceptions handling, fix for 'mode x, y'
Browse files Browse the repository at this point in the history
  • Loading branch information
alabuzhev committed Aug 24, 2016
1 parent f5096f8 commit 5fb8519
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 80 deletions.
6 changes: 6 additions & 0 deletions far/changelog
@@ -1,3 +1,9 @@
drkns 24.08.2016 18:08:24 +0200 - build 4766

1. Уточнения обработки исключений.

2. После 4709 не работало изменение размера консоли с помощью "mode x, y".

drkns 23.08.2016 11:20:47 +0200 - build 4765

1. Не работал поиск в UTF8-файлах во вьювере.
Expand Down
7 changes: 5 additions & 2 deletions far/execute.cpp
Expand Up @@ -1064,9 +1064,12 @@ void Execute(execute_info& Info, bool FolderRun, bool Silent, const std::functio
CONSOLE_CURSOR_INFO cci = { CursorSize, Visible };
Console().SetCursorInfo(cci);

if (IsConsoleSizeChanged())
{
ChangeVideoMode(ScrY, ScrX);
COORD ConSize;
if (Console().GetSize(ConSize) && (ConSize.X != ScrX + 1 || ConSize.Y != ScrY + 1))
{
ChangeVideoMode(ConSize.Y, ConSize.X);
}
}

if (Global->Opt->Exec.RestoreCPAfterExecute)
Expand Down
128 changes: 91 additions & 37 deletions far/farexcpt.cpp
Expand Up @@ -519,24 +519,39 @@ void RestoreGPFaultUI()
SetErrorMode(Global->ErrorMode&~SEM_NOGPFAULTERRORBOX);
}

bool ProcessSEHException(EXCEPTION_POINTERS *xp, const wchar_t* Function, Plugin *PluginModule)
{
return ProcessGenericException(xp, Function, PluginModule, nullptr);
}

bool ProcessStdException(const std::exception& e, const wchar_t* Function, Plugin* Module)
{
EXCEPTION_RECORD ExceptionRecord {};
CONTEXT ContextRecord {};
EXCEPTION_RECORD ExceptionRecord{};
CONTEXT ContextRecord{};
EXCEPTION_POINTERS xp = { &ExceptionRecord, &ContextRecord };
if (!tracer::get_exception_context(&e, ExceptionRecord, ContextRecord))

EXCEPTION_POINTERS* XpPtr;

if (const auto se = dynamic_cast<const SException*>(&e))
{
// std::exception to EXCEPTION_POINTERS translation relies on Microsoft C++ exception implementation.
// It won't work in gcc etc.
// Set ExceptionCode manually so ProcessGenericException will at least report it as std::exception and display what()
xp.ExceptionRecord->ExceptionCode = EXCEPTION_MICROSOFT_CPLUSPLUS;
XpPtr = se->GetInfo();
}
return ProcessGenericException(&xp, Function, Module, e.what());
else
{
if (!tracer::get_exception_context(&e, ExceptionRecord, ContextRecord))
{
// std::exception to EXCEPTION_POINTERS translation relies on Microsoft C++ exception implementation.
// It won't work in gcc etc.
// Set ExceptionCode manually so ProcessGenericException will at least report it as std::exception and display what()
xp.ExceptionRecord->ExceptionCode = EXCEPTION_MICROSOFT_CPLUSPLUS;
}
XpPtr = &xp;
}
return ProcessGenericException(XpPtr, Function, Module, e.what());
}

bool ProcessUnknownException(const wchar_t* Function, Plugin* Module)
{
EXCEPTION_RECORD ExceptionRecord{};
CONTEXT ContextRecord{};
EXCEPTION_POINTERS xp = { &ExceptionRecord, &ContextRecord };

return ProcessGenericException(&xp, Function, Module, nullptr);
}

LONG WINAPI FarUnhandledExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo)
Expand All @@ -550,22 +565,22 @@ LONG WINAPI FarUnhandledExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo)
}


static DWORD WINAPI ProcessSEHExceptionWrapper(EXCEPTION_POINTERS* xp)
static DWORD WINAPI ProcessGenericExceptionWrapper(EXCEPTION_POINTERS* xp)
{
ProcessSEHException(xp, nullptr);
ProcessGenericException(xp, nullptr, nullptr, nullptr);
return 0;
}

LONG WINAPI VectoredExceptionHandler(EXCEPTION_POINTERS *xp)
{
// restore stack & call ProcessSEHExceptionWrapper
// restore stack & call ProcessGenericExceptionWrapper
if (xp->ExceptionRecord->ExceptionCode == (DWORD)STATUS_STACK_OVERFLOW)
{
#if 1 // it is much better way than hack stack and modify original context
//#ifdef _M_IA64
// TODO: Bad way to restore IA64 stacks (CreateThread)
// Can you do smartly? See REMINDER file, section IA64Stacks
static HANDLE hThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)ProcessSEHExceptionWrapper, xp, 0, nullptr);
static HANDLE hThread = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(ProcessGenericExceptionWrapper), xp, 0, nullptr);
if (hThread)
{
WaitForSingleObject(hThread, INFINITE);
Expand All @@ -587,14 +602,14 @@ LONG WINAPI VectoredExceptionHandler(EXCEPTION_POINTERS *xp)
//stack.args[2] = ...
//stack.args[3] = ...
xp->ContextRecord->Esp = reinterpret_cast<DWORD_PTR>(&stack.ret_addr);
xp->ContextRecord->Eip = reinterpret_cast<DWORD_PTR>(&ProcessSEHExceptionWrapper);
xp->ContextRecord->Eip = reinterpret_cast<DWORD_PTR>(&ProcessGenericExceptionWrapper);
#else
xp->ContextRecord->Rcx = reinterpret_cast<DWORD_PTR>(xp);
//xp->ContextRecord->Rdx = ...
//xp->ContextRecord->R8 = ...
//xp->ContextRecord->R9 = ...
xp->ContextRecord->Rsp = reinterpret_cast<DWORD_PTR>(&stack.ret_addr);
xp->ContextRecord->Rip = reinterpret_cast<DWORD_PTR>(&ProcessSEHExceptionWrapper);
xp->ContextRecord->Rip = reinterpret_cast<DWORD_PTR>(&ProcessGenericExceptionWrapper);
#endif
return EXCEPTION_CONTINUE_EXECUTION;
#endif
Expand Down Expand Up @@ -646,9 +661,28 @@ static int ExceptionTestHook(Manager::Key key)
key() == KEY_RCTRLALTAPPS
)
{
enum class exception_types
{
cpp_std,
cpp_unknown,
access_violation_read,
access_violation_write,
divide_by_zero,
illegal_instruction,
stack_overflow,
fp_divide_by_zero,
breakpoint,
#ifdef _M_IA64
alignment_fault,
#endif

count
};

static const wchar_t* Names[] =
{
L"C++ std::exception",
L"C++ unknown exception",
L"Access Violation (Read)",
L"Access Violation (Write)",
L"Divide by zero",
Expand Down Expand Up @@ -677,6 +711,9 @@ static int ExceptionTestHook(Manager::Key key)
L"EXCEPTION_INVALID_HANDLE",
*/
};

static_assert(std::size(Names) == static_cast<size_t>(exception_types::count), "Incomplete Names array");

static union
{
int i;
Expand All @@ -694,23 +731,32 @@ static int ExceptionTestHook(Manager::Key key)
});

int ExitCode = ModalMenu->Run();
if (ExitCode == -1)
return TRUE;

switch (ExitCode)
switch (static_cast<exception_types>(ExitCode))
{
case -1:
return TRUE;
case 0:
case exception_types::cpp_std:
throw MAKE_FAR_EXCEPTION("test error");
case 1:
break;

case exception_types::cpp_unknown:
throw 42;
break;

case exception_types::access_violation_read:
zero_const.i = *zero_const.iptr;
break;
case 2:

case exception_types::access_violation_write:
*zero_const.iptr = 0;
break;
case 3:

case exception_types::divide_by_zero:
zero_const.i = 1 / zero_const.i;
break;
case 4:

case exception_types::illegal_instruction:
#if COMPILER == C_CL || COMPILER == C_INTEL
#ifdef _M_IA64
const int REG_IA64_IntR0 = 1024;
Expand All @@ -722,24 +768,32 @@ static int ExceptionTestHook(Manager::Key key)
asm("ud2");
#endif
break;
case 5:

case exception_types::stack_overflow:
Test_EXCEPTION_STACK_OVERFLOW(nullptr);
break;
case 6:

case exception_types::fp_divide_by_zero:
zero_const.d = 1.0 / zero_const.d;
break;
case 7:

case exception_types::breakpoint:
DebugBreak();
break;

#ifdef _M_IA64
case 8:
{
BYTE temp[10] = {};
double* val;
val = (double*)(&temp[3]);
printf("%lf\n", *val);
}
case exception_types::alignment_fault:
{
BYTE temp[10] = {};
double* val;
val = (double*)(&temp[3]);
printf("%lf\n", *val);
break;
}
#endif
case exception_types::count:
// makes no sense, just to make compiler happy
break;
}

Message(MSG_WARNING, 1, L"Test Exceptions failed", L"", Names[ExitCode], L"", MSG(MOk));
Expand Down
2 changes: 1 addition & 1 deletion far/farexcpt.hpp
Expand Up @@ -37,8 +37,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

class Plugin;

bool ProcessSEHException(EXCEPTION_POINTERS *xp, const wchar_t* Function, Plugin *Module = nullptr);
bool ProcessStdException(const std::exception& e, const wchar_t* Function, Plugin* Module = nullptr);
bool ProcessUnknownException(const wchar_t* Function, Plugin* Module = nullptr);

LONG WINAPI FarUnhandledExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo);

Expand Down
37 changes: 26 additions & 11 deletions far/findfile.cpp
Expand Up @@ -1373,6 +1373,17 @@ bool background_searcher::IsFileIncluded(PluginPanelItem* FileItem, const string
intptr_t FindFiles::FindDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2)
{
SCOPED_ACTION(CriticalSectionLock)(PluginCS);

if (!m_ExceptionPtr)
{
m_ExceptionPtr = m_Searcher->ExceptionPtr();
if (m_ExceptionPtr)
{
Dlg->SendMessage(DM_CLOSE, 0, nullptr);
return TRUE;
}
}

auto& ListBox = Dlg->GetAllItem()[FD_LISTBOX].ListPtr;

static bool Recurse=false;
Expand Down Expand Up @@ -2628,16 +2639,9 @@ unsigned int background_searcher::ThreadRoutine(THREADPARAM* Param)
Param->PluginMode? DoPreparePluginList(Param->Dlg, false) : DoPrepareFileList(Param->Dlg);
ReleaseInFileSearch();
}
catch (const SException& e)
catch (...)
{
if (ProcessSEHException(e.GetInfo(), L"FindFiles::ThreadRoutine"))
{
std::terminate();
}
else
{
throw;
}
m_ExceptionPtr = std::current_exception();
}
return 0;
}
Expand Down Expand Up @@ -2754,9 +2758,20 @@ bool FindFiles::FindFilesProcess()

Thread FindThread(&Thread::join, &background_searcher::ThreadRoutine, &BC, &Param);
Dlg->Process();

// BUGBUG
m_Searcher = nullptr;

if (!m_ExceptionPtr)
{
m_ExceptionPtr = BC.ExceptionPtr();
}

if (m_ExceptionPtr)
{
std::rethrow_exception(m_ExceptionPtr);
}
}
// BUGBUG
m_Searcher = nullptr;

switch (Dlg->GetExitCode())
{
Expand Down
5 changes: 5 additions & 0 deletions far/findfile.hpp
Expand Up @@ -124,6 +124,7 @@ class FindFiles: noncopyable
time_check m_TimeCheck;
// BUGBUG
class background_searcher* m_Searcher;
std::exception_ptr m_ExceptionPtr;
};

class background_searcher: noncopyable
Expand All @@ -148,6 +149,8 @@ class background_searcher: noncopyable
void Stop() const { StopEvent.Set(); }
bool Stopped() const { return StopEvent.Signaled(); }

auto ExceptionPtr() const { return m_ExceptionPtr; }

private:
void InitInFileSearch();
void ReleaseInFileSearch();
Expand Down Expand Up @@ -196,5 +199,7 @@ class background_searcher: noncopyable

Event PauseEvent;
Event StopEvent;

std::exception_ptr m_ExceptionPtr;
};
#endif // FINDFILE_HPP_8601893C_E4B7_4EC6_A79F_9C6E491FF5ED
1 change: 0 additions & 1 deletion far/initguid.cpp
Expand Up @@ -32,7 +32,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <initguid.h>

#include "headers.hpp"
#include "FarGuid.hpp"
#include "DlgGuid.hpp"
#include "KnownGuids.hpp"
24 changes: 0 additions & 24 deletions far/main.cpp
Expand Up @@ -766,18 +766,6 @@ static int mainImpl(const range<wchar_t**>& Args)
{
Result = MainProcess(strEditName, strViewName, DestNames[0], DestNames[1], StartLine, StartChar);
}
catch (const SException& e)
{
if (ProcessSEHException(e.GetInfo(), L"mainImpl"))
{
std::terminate();
}
else
{
RestoreGPFaultUI();
throw;
}
}
catch (const std::exception& e)
{
if (ProcessStdException(e, L"mainImpl"))
Expand Down Expand Up @@ -819,18 +807,6 @@ int wmain(int Argc, wchar_t *Argv[])
static SCOPED_ACTION(os::com::co_initialize);
return mainImpl(make_range(Argv + 1, Argv + Argc));
}
catch (const SException& e)
{
if (ProcessSEHException(e.GetInfo(), L"wmain"))
{
std::terminate();
}
else
{
SetUnhandledExceptionFilter(nullptr);
throw;
}
}
catch (const std::exception& e)
{
if (ProcessStdException(e, L"wmain"))
Expand Down
1 change: 1 addition & 0 deletions far/makefile_gcc_common
Expand Up @@ -76,6 +76,7 @@ CFLAGS += \
CCFLAGS = $(CFLAGS) -std=c++1z \
-Wnon-virtual-dtor \
-Woverloaded-virtual \
-Wctor-dtor-privacy \
-Wzero-as-null-pointer-constant \
-Wsuggest-final-types \
-Wsuggest-final-methods \
Expand Down

0 comments on commit 5fb8519

Please sign in to comment.