int TestEnv::RunProcessTestCase(TestCase& obj, void(TestCase::*meth)(), int timeout) { TestCaseCall call(obj, meth); TestEnv::in_child_process = true; HANDLE thread = (HANDLE)_beginthread( ThreadProc, 0, &call ); if (thread == NULL) { REPORT_ERROR("TestEnv::RunProcessTestCase: failed to start a test case thread"); } // make sure to restore main process's signal handlers before re-throwing an exception DWORD rc=0; DWORD result=WaitForSingleObject( (HANDLE)thread, timeout == 0 ? INFINITE : timeout*1000); try { switch (result) { case WAIT_OBJECT_0: if (GetExitCodeThread(thread, &rc) == 0) REPORT_ERROR("RunProcessTestCase failed"); break; case WAIT_TIMEOUT: if (!CloseHandle(thread)) REPORT_ERROR("CloseHandle failed"); cerr << "child process timed out" << endl; rc=TEST_CASE_TIMED_OUT; break; default: REPORT_ERROR("WaitForSingleObject failed"); break; } } catch (const exception& ex) { REPORT_ERROR(obj.GetName() + " threw " + ex.what()); rc=TEST_CASE_FAILED; } catch (const ncbi::NK::execution_aborted&) { REPORT_ERROR(obj.GetName() + " aborted "); rc=TEST_CASE_FAILED; } catch (...) { REPORT_ERROR(obj.GetName() + " threw something "); rc=TEST_CASE_FAILED; set_handlers(); throw; } #undef CALL_FAILED set_handlers(); in_child_process = false; return (int)rc; }
int TestEnv::RunProcessTestCase(TestCase& obj, void(TestCase::*meth)(), int timeout) { int pid=fork(); if (pid == -1) { REPORT_ERROR("RunProcessTestCase: fork() failed"); } if (pid == 0) { /* child process */ if (timeout != 0) { struct sigaction act; memset(&act, 0, sizeof act); act.sa_handler = alarmHandler; act.sa_flags = SA_RESETHAND; sigaction(SIGALRM , &act, NULL); alarm(timeout); } try { in_child_process = true; (obj.*meth)(); } catch (const exception& ex) { cerr << obj.GetName() << " threw " << ex.what() << endl; exit(TEST_CASE_FAILED); } catch (const ncbi::NK::execution_aborted&) { cerr << obj.GetName() << " aborted " << endl; exit(TEST_CASE_FAILED); } catch (...) { cerr << obj.GetName() << " threw something " << endl; exit(TEST_CASE_FAILED); } exit(0); } /* parent process */ int status; if (waitpid(pid, &status, 0) != pid) /* suspend until the child terminates */ { REPORT_ERROR("RunProcessTestCase: wait() failed"); } if (!WIFEXITED(status)) { REPORT_ERROR("RunProcessTestCase: child exited abnormally"); } return WEXITSTATUS(status); /* exit status of the child process */ }