Beispiel #1
0
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 */
}