Я пытаюсь настроить тестовое программное обеспечение для кода, который уже написан (что я не могу изменить). Проблема, с которой я сталкиваюсь, заключается в том, что она зависает на определенных вызовах, поэтому я хочу попытаться реализовать что-то, что убьет процесс, если он не завершится через х секунд.
Эти два метода, которые я пытался решить эту проблему, заключались в использовании fork или pthread, оба пока не работали для меня. Я не уверен, почему pthread не работает, я предполагаю, потому что статический вызов, который я использовал для создания потока, имел некоторые проблемы с памятью, необходимой для запуска функции, которую я вызывал (я постоянно получал segfault, в то время как функция, которую я тестировал). Вилка работала изначально, но во второй раз я бы расколол процесс, он не смог бы проверить, закончил ли ребенок или нет.
В терминах полу-псевдокода это то, что я написал
test_runner()
{
bool result;
testClass* myTestClass = new testClass();
pid_t pID = fork();
if(pID == 0) //Child
{
myTestClass->test_function(); //function in question being tested
}
else if(pID > 0) //Parent
{
int status;
sleep(5);
if(waitpid(0,&status,WNOHANG) == 0)
{
kill(pID,SIGKILL); //If child hasn't finished, kill process and fail test
result = false;
}
else
result = true;
}
}
Этот метод работал для первоначального теста, но затем, когда я перейду к проверке второй функции, if (waitpid (0, & status, WNOHANG) == 0) вернет, что ребенок закончил, даже если этого не произошло.
Метод pthread рассматривал эти строки
bool result;
test_runner()
{
long thread = 1;
pthread_t* thread_handle = (pthread_t*) malloc (sizeof(pthread_t));
pthread_create(&thread_handle[thread], NULL, &funcTest, (void *)&thread); //Begin class that tests function in question
sleep(10);
if(pthread_cancel(thread_handle[thread] == 0))
//Child process got stuck, deal with accordingly
else
//Child process did not get stuck, deal with accordingly
}
static void* funcTest(void*)
{
result = false;
testClass* myTestClass = new testClass();
result = myTestClass->test_function();
}
Очевидно, что происходит немного больше, чем то, что я показал, я просто хотел опустить общую идею. Я предполагаю, что я ищу, если есть лучший способ справиться с проблемой, подобной этой, или, может быть, если кто-то увидит какие-то вопиющие проблемы с тем, что я пытаюсь сделать (я относительно новичок в C++). Как я уже упоминал, мне не разрешено входить в код, который я настраиваю для тестового программного обеспечения, что мешает мне помещать обработчики сигналов в функцию, которую я тестирую. Я могу только вызвать функцию, а затем обработать ее оттуда.
Если С++ 11 является законным, вы можете использовать future
с wait_for
для этой цели.
Например (живая демонстрация):
std::future<int> future = std::async(std::launch::async, [](){
std::this_thread::sleep_for(std::chrono::seconds(3));
return 8;
});
std::future_status status = future.wait_for(std::chrono::seconds(5));
if (status == std::future_status::timeout) {
std::cout << "Timeout" <<endl ;
} else{
cout << "Success" <<endl ;
} // will print Success
std::future<int> future2 = std::async(std::launch::async, [](){
std::this_thread::sleep_for(std::chrono::seconds(3));
return 8;
});
std::future_status status2 = future2.wait_for(std::chrono::seconds(1));
if (status2 == std::future_status::timeout) {
std::cout << "Timeout" <<endl ;
} else{
cout << "Success" <<endl ;
} // will print Timeout
Еще одна вещь:
Согласно документации с использованием waitpid
с 0
:
что означает ожидание любого дочернего процесса, идентификатор группы процессов которого совпадает с идентификатором вызывающего процесса.
Избегайте использования pthread_cancel
это, вероятно, не очень хорошая идея.
pID
вместо0
вwaitpid(0,&status,WNOHANG)
?