tests: add failsafe timeout for tests running in fork mode

some tests manage to deadlock themselves on travis, seemingly due to some
hard to reproduce issues which are a result of the extremely low amount of
resources available on travis builds

this adds a simple 'timeout' process which does nothing but sleep(60);
and then returns. the exiting of this process will cause the main test
process to break out of the deadlock and then exit instead of timing out
a ci build

Differential Revision: https://phab.enlightenment.org/D6697
This commit is contained in:
Mike Blumenkrantz 2018-07-30 12:50:58 -04:00 committed by Stefan Schmidt
parent 1320ba435e
commit 440b7ce03f
4 changed files with 63 additions and 10 deletions

View File

@ -125,6 +125,10 @@ endif
DIST_SUBDIRS += $(EXAMPLES_SUBDIRS)
if EFL_ENABLE_TESTS
noinst_PROGRAMS += tests/timeout
$(check_PROGRAMS): tests/timeout
check-build: all
@$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
endif

View File

@ -4,3 +4,4 @@ check-results*.xml
*_suite.trs
*.node
*/cxx_compile_test
/timeout

View File

@ -13,8 +13,13 @@
#include <sys/time.h>
#ifdef HAVE_FORK
#include <sys/types.h>
#include <sys/wait.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#include <signal.h>
#include <Eina.h>
#endif
@ -55,6 +60,8 @@ struct _Efl_Test_Case
void (*build)(TCase *tc);
};
static int timeout_pid = 0;
static void
_efl_tests_list(const Efl_Test_Case *etc)
{
@ -247,15 +254,18 @@ _efl_suite_run_end(SRunner *sr, const char *name)
#ifdef HAVE_FORK
EINA_UNUSED static int
_efl_suite_wait_on_fork(int *num_forks)
_efl_suite_wait_on_fork(int *num_forks, Eina_Bool *timeout)
{
int status = 0, ret;
waitpid(0, &status, 0);
int status = 0, ret, pid;
pid = waitpid(0, &status, 0);
if (WIFEXITED(status))
ret = WEXITSTATUS(status);
else
ret = 1;
(*num_forks)--;
if (pid == timeout_pid)
*timeout = EINA_TRUE;
else
(*num_forks)--;
return ret;
}
#endif
@ -270,6 +280,7 @@ _efl_suite_build_and_run(int argc, const char **argv, const char *suite_name, co
int do_fork;
int num_forks = 0;
int can_fork = 0;
Eina_Bool timeout_reached = EINA_FALSE;
#ifdef ENABLE_TIMING_INFO
double tstart, tcstart;
int timing = _timing_enabled();
@ -293,8 +304,15 @@ _efl_suite_build_and_run(int argc, const char **argv, const char *suite_name, co
#ifdef HAVE_FORK
if (do_fork && can_fork)
{
if (!timeout_pid)
{
timeout_pid = fork();
if (!timeout_pid)
execl("/bin/sh", "/bin/sh", "-c", PACKAGE_BUILD_DIR "/src/tests/timeout", (char *)NULL);
}
if (num_forks == eina_cpu_count())
failed_count += _efl_suite_wait_on_fork(&num_forks);
failed_count += _efl_suite_wait_on_fork(&num_forks, &timeout_reached);
if (timeout_reached) break;
pid = fork();
if (pid > 0)
{
@ -333,17 +351,32 @@ _efl_suite_build_and_run(int argc, const char **argv, const char *suite_name, co
}
#ifdef HAVE_FORK
if (num_forks)
if (num_forks && (!timeout_reached))
{
do
{
failed_count += _efl_suite_wait_on_fork(&num_forks);
} while (num_forks);
failed_count += _efl_suite_wait_on_fork(&num_forks, &timeout_reached);
} while (num_forks && (!timeout_reached));
if (timeout_reached)
{
timeout_pid = 0;
printf("FAILSAFE TIMEOUT REACHED!\n");
fflush(stdout);
failed_count++;
}
}
else
#endif
failed_count = _efl_suite_run_end(sr, NULL);
#ifdef HAVE_FORK
if (timeout_pid)
{
kill(timeout_pid, SIGKILL);
timeout_pid = 0;
}
#endif
#ifdef ENABLE_TIMING_INFO
if (timing)
{

15
src/tests/timeout.c Normal file
View File

@ -0,0 +1,15 @@
#include <unistd.h>
#if defined(__clang__)
# pragma clang diagnostic ignored "-Wunused-parameter"
#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4
# pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
int
main(int arc, char *argv[])
{
sleep(60);
return 0;
}