From: Jan S. <jst...@re...> - 2013-07-24 06:39:48
|
Test can send SIGUSR1 signal after thread has already completed and report failure from main() and success from a_thread_func(): conformance/interfaces/mq_timedsend/12-1: execution: UNRESOLVED: Output: Error: in pthread_kill : Success thread: mq_timedsend interrupted by signal and correctly set errno to EINTR Synchronize exit of a_thread_func(), so that thread can exit only after loop sending SIGUSR1 completed. Signed-off-by: Jan Stancek <jst...@re...> --- .../conformance/interfaces/mq_timedsend/12-1.c | 94 +++++++++++--------- 1 files changed, 51 insertions(+), 43 deletions(-) diff --git a/testcases/open_posix_testsuite/conformance/interfaces/mq_timedsend/12-1.c b/testcases/open_posix_testsuite/conformance/interfaces/mq_timedsend/12-1.c index 29780d0..df53a72 100644 --- a/testcases/open_posix_testsuite/conformance/interfaces/mq_timedsend/12-1.c +++ b/testcases/open_posix_testsuite/conformance/interfaces/mq_timedsend/12-1.c @@ -39,19 +39,25 @@ #define MSGSTR "0123456789" #define BUFFER 40 #define MAXMSG 10 +#define TIMEOUT 10 -#define INTHREAD 0 -#define INMAIN 1 +#define SAFE(op) \ + do {\ + if ((op) == -1) {\ + perror("unexpected failure"); \ + exit(PTS_UNRESOLVED); \ + } \ + } while (0) -/* manual semaphore */ -int sem; +/* variable to indicate how many times signal handler was called */ +static volatile sig_atomic_t in_handler; -/* flag to indicate signal handler was called */ -int in_handler; +/* errno returned by mq_timedsend() */ +static volatile int mq_timedsend_errno = -1; -/* flag to indicate that errno was set to eintr when mq_timedsend() - * was interruped. */ -int errno_eintr; +/* pipes to synchronize thread calling mq_timedsend */ +static int pipefd_start[2]; +static int pipefd_exit[2]; /* * This handler is just used to catch the signal and stop sleep (so the @@ -59,14 +65,12 @@ int errno_eintr; */ void justreturn_handler(int signo) { - /* Indicate that the signal handler was called */ - in_handler = 1; - return; + in_handler++; } -void *a_thread_func() +void *a_thread_func(void *arg) { - int i, ret; + int i, ret, dummy; struct sigaction act; char gqname[NAMESIZE]; mqd_t gqueue; @@ -92,18 +96,19 @@ void *a_thread_func() return NULL; } - /* mq_timedsend will block for 10 seconds when it waits */ - ts.tv_sec = time(NULL) + 10; + /* mq_timedsend will block for TIMEOUT seconds when it waits */ + ts.tv_sec = time(NULL) + TIMEOUT; ts.tv_nsec = 0; /* Tell main it can go ahead and start sending SIGUSR1 signal */ - sem = INMAIN; + SAFE(write(pipefd_start[1], "", 1)); for (i = 0; i < MAXMSG + 1; i++) { ret = mq_timedsend(gqueue, msgptr, strlen(msgptr), 1, &ts); if (ret != -1) continue; + mq_timedsend_errno = errno; if (errno == EINTR) { if (mq_unlink(gqname) != 0) { perror("mq_unlink() did not return success"); @@ -112,21 +117,24 @@ void *a_thread_func() } printf("thread: mq_timedsend interrupted by signal" " and correctly set errno to EINTR\n"); - errno_eintr = 1; + /* wait for main to stop sending SIGUSR1 */ + SAFE(read(pipefd_exit[0], &dummy, 1)); pthread_exit((void *)PTS_PASS); return NULL; } else { printf("mq_timedsend not interrupted by signal or" " set errno to incorrect code: %d\n", errno); + /* wait for main to stop sending SIGUSR1 */ + SAFE(read(pipefd_exit[0], &dummy, 1)); pthread_exit((void *)PTS_FAIL); return NULL; } } - /* Tell main that it the thread did not block like it should have */ - sem = INTHREAD; - - perror("Error: thread never blocked\n"); + mq_timedsend_errno = 0; + printf("Error: mq_timedsend wasn't interrupted\n"); + /* wait for main to stop sending SIGUSR1 */ + SAFE(read(pipefd_exit[0], &dummy, 1)); pthread_exit((void *)PTS_FAIL); return NULL; } @@ -134,13 +142,10 @@ void *a_thread_func() int main(void) { pthread_t new_th; - int i; + int i = 0, ret, dummy; - /* Initialized values */ - i = 0; - in_handler = 0; - errno_eintr = 0; - sem = INTHREAD; + SAFE(pipe(pipefd_start)); + SAFE(pipe(pipefd_exit)); if (pthread_create(&new_th, NULL, a_thread_func, NULL) != 0) { perror("Error: in pthread_create\n"); @@ -148,18 +153,22 @@ int main(void) } /* Wait for thread to set up handler for SIGUSR1 */ - while (sem == INTHREAD) - sleep(1); + SAFE(read(pipefd_start[0], &dummy, 1)); - while ((i != 10) && (sem == INMAIN)) { + while (i < TIMEOUT && mq_timedsend_errno < 0) { /* signal thread while it's in mq_timedsend */ - if (pthread_kill(new_th, SIGUSR1) != 0) { - perror("Error: in pthread_kill\n"); + ret = pthread_kill(new_th, SIGUSR1); + if (ret != 0) { + printf("Error: in pthread_kill: %d\n", ret); return PTS_UNRESOLVED; } i++; + sleep(1); } + /* signal thread it's OK to exit now */ + SAFE(write(pipefd_exit[1], "", 1)); + if (pthread_join(new_th, NULL) != 0) { perror("Error: in pthread_join()\n"); return PTS_UNRESOLVED; @@ -167,18 +176,17 @@ int main(void) /* Test to see if the thread blocked correctly in mq_timedsend, * and if it returned EINTR when it caught the signal */ - if (errno_eintr != 1) { - if (sem == INTHREAD) { - printf("Test FAILED: mq_timedsend() never" - " blocked for any timeout period.\n"); - return PTS_FAIL; - } - - if (in_handler != 0) { - perror("Error: signal SIGUSR1 was never received and/or" - " the signal handler was never called.\n"); + if (mq_timedsend_errno != EINTR) { + printf("Error: mq_timedsend was NOT interrupted\n"); + printf(" signal handler was called %d times\n", in_handler); + printf(" SIGUSR1 signals sent: %d\n", i); + printf(" last mq_timedsend errno: %d %s\n", + mq_timedsend_errno, strerror(mq_timedsend_errno)); + if (in_handler == 0) { + printf("Error: SIGUSR1 was never received\n"); return PTS_UNRESOLVED; } + return PTS_FAIL; } printf("Test PASSED\n"); -- 1.7.1 |