VM: implement a ctrl-break handler thread (#1573)
parent
ea2a856ee6
commit
526a995d64
|
@ -8,7 +8,7 @@ GIT_LABEL = git-label-missing
|
||||||
|
|
||||||
!IF DEFINED(PLATFORM)
|
!IF DEFINED(PLATFORM)
|
||||||
|
|
||||||
LINK_FLAGS = /nologo shell32.lib
|
LINK_FLAGS = /nologo shell32.lib user32.lib
|
||||||
CL_FLAGS = /nologo /O2 /WX /W3 /D_CRT_SECURE_NO_WARNINGS /DFACTOR_VERSION=$(VERSION) /DFACTOR_GIT_LABEL=$(GIT_LABEL)
|
CL_FLAGS = /nologo /O2 /WX /W3 /D_CRT_SECURE_NO_WARNINGS /DFACTOR_VERSION=$(VERSION) /DFACTOR_GIT_LABEL=$(GIT_LABEL)
|
||||||
CL_FLAGS_VISTA = /D_WIN32_WINNT=0x0600
|
CL_FLAGS_VISTA = /D_WIN32_WINNT=0x0600
|
||||||
|
|
||||||
|
|
|
@ -474,6 +474,14 @@ void handle_ctrl_c() {
|
||||||
sigaction_safe(SIGINT, &fep_sigaction, NULL);
|
sigaction_safe(SIGINT, &fep_sigaction, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void factor_vm::primitive_disable_ctrl_break() {
|
||||||
|
stop_on_ctrl_break = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void factor_vm::primitive_enable_ctrl_break() {
|
||||||
|
stop_on_ctrl_break = true;
|
||||||
|
}
|
||||||
|
|
||||||
void abort() {
|
void abort() {
|
||||||
sig_t ret;
|
sig_t ret;
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -294,6 +294,50 @@ void handle_ctrl_c() {
|
||||||
SetConsoleCtrlHandler(factor::ctrl_handler, TRUE);
|
SetConsoleCtrlHandler(factor::ctrl_handler, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int ctrl_break_sleep = 10; /* msec */
|
||||||
|
|
||||||
|
static DWORD WINAPI ctrl_break_thread_proc(LPVOID parent_vm) {
|
||||||
|
bool ctrl_break_handled = false;
|
||||||
|
factor_vm* vm = static_cast<factor_vm*>(parent_vm);
|
||||||
|
while (vm->stop_on_ctrl_break) {
|
||||||
|
if (GetAsyncKeyState(VK_CANCEL) >= 0) { /* Ctrl-Break is released. */
|
||||||
|
ctrl_break_handled = false; /* Wait for the next press. */
|
||||||
|
} else if (!ctrl_break_handled) {
|
||||||
|
/* Check if the VM thread has the same Id as the thread Id of the
|
||||||
|
currently active window. Note that thread Id is not a handle. */
|
||||||
|
DWORD fg_thd_id = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
|
||||||
|
if ((fg_thd_id == vm->thread_id) && !vm->fep_p) {
|
||||||
|
vm->enqueue_fep();
|
||||||
|
ctrl_break_handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Sleep(ctrl_break_sleep);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void factor_vm::primitive_disable_ctrl_break() {
|
||||||
|
stop_on_ctrl_break = false;
|
||||||
|
if (ctrl_break_thread != NULL) {
|
||||||
|
DWORD wait_result = WaitForSingleObject(ctrl_break_thread,
|
||||||
|
2 * ctrl_break_sleep);
|
||||||
|
if (wait_result != WAIT_OBJECT_0)
|
||||||
|
TerminateThread(ctrl_break_thread, 0);
|
||||||
|
CloseHandle(ctrl_break_thread);
|
||||||
|
ctrl_break_thread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void factor_vm::primitive_enable_ctrl_break() {
|
||||||
|
stop_on_ctrl_break = true;
|
||||||
|
if (ctrl_break_thread == NULL) {
|
||||||
|
DisableProcessWindowsGhosting();
|
||||||
|
ctrl_break_thread = CreateThread(NULL, 0, factor::ctrl_break_thread_proc,
|
||||||
|
static_cast<LPVOID>(this), 0, NULL);
|
||||||
|
SetThreadPriority(ctrl_break_thread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void lock_console() {}
|
void lock_console() {}
|
||||||
|
|
||||||
void unlock_console() {}
|
void unlock_console() {}
|
||||||
|
|
|
@ -35,11 +35,18 @@ void factor_vm::handle_safepoint(cell pc) {
|
||||||
faulting_p = false;
|
faulting_p = false;
|
||||||
|
|
||||||
if (atomic::load(&safepoint_fep_p)) {
|
if (atomic::load(&safepoint_fep_p)) {
|
||||||
|
atomic::store(&safepoint_fep_p, false);
|
||||||
if (atomic::load(&sampling_profiler_p))
|
if (atomic::load(&sampling_profiler_p))
|
||||||
end_sampling_profiler();
|
end_sampling_profiler();
|
||||||
std::cout << "Interrupted\n";
|
std::cout << "Interrupted\n";
|
||||||
|
if (stop_on_ctrl_break) {
|
||||||
|
/* Ctrl-Break throws an exception, interrupting the main thread, same
|
||||||
|
as the "t" command in the factorbug debugger. But for Ctrl-Break to
|
||||||
|
work we don't require the debugger to be activated, or even enabled. */
|
||||||
|
general_error(ERROR_INTERRUPT, false_object, false_object);
|
||||||
|
FACTOR_ASSERT(false);
|
||||||
|
}
|
||||||
factorbug();
|
factorbug();
|
||||||
atomic::store(&safepoint_fep_p, false);
|
|
||||||
} else if (atomic::load(&sampling_profiler_p)) {
|
} else if (atomic::load(&sampling_profiler_p)) {
|
||||||
FACTOR_ASSERT(code->seg->in_segment_p(pc));
|
FACTOR_ASSERT(code->seg->in_segment_p(pc));
|
||||||
code_block* block = code->code_block_for_address(pc);
|
code_block* block = code->code_block_for_address(pc);
|
||||||
|
|
|
@ -7,6 +7,11 @@ factor_vm::factor_vm(THREADHANDLE thread)
|
||||||
nursery(0, 0),
|
nursery(0, 0),
|
||||||
faulting_p(false),
|
faulting_p(false),
|
||||||
thread(thread),
|
thread(thread),
|
||||||
|
#if defined(WINDOWS)
|
||||||
|
thread_id(GetCurrentThreadId()),
|
||||||
|
ctrl_break_thread(NULL),
|
||||||
|
stop_on_ctrl_break(false),
|
||||||
|
#endif
|
||||||
callback_id(0),
|
callback_id(0),
|
||||||
c_to_factor_func(NULL),
|
c_to_factor_func(NULL),
|
||||||
sampling_profiler_p(false),
|
sampling_profiler_p(false),
|
||||||
|
|
|
@ -393,6 +393,7 @@ struct factor_vm {
|
||||||
void factorbug_usage(bool advanced_p);
|
void factorbug_usage(bool advanced_p);
|
||||||
void factorbug();
|
void factorbug();
|
||||||
void primitive_die();
|
void primitive_die();
|
||||||
|
volatile bool stop_on_ctrl_break;
|
||||||
|
|
||||||
// arrays
|
// arrays
|
||||||
inline void set_array_nth(array* array, cell slot, cell value);
|
inline void set_array_nth(array* array, cell slot, cell value);
|
||||||
|
@ -701,6 +702,11 @@ struct factor_vm {
|
||||||
|
|
||||||
// os-windows
|
// os-windows
|
||||||
#if defined(WINDOWS)
|
#if defined(WINDOWS)
|
||||||
|
/* Id of the main thread we run in. Used for Ctrl-Break handling. */
|
||||||
|
DWORD thread_id;
|
||||||
|
|
||||||
|
HANDLE ctrl_break_thread;
|
||||||
|
|
||||||
HANDLE sampler_thread;
|
HANDLE sampler_thread;
|
||||||
void sampler_thread_loop();
|
void sampler_thread_loop();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue