This test is racy. It relies on signals interrupting sleeps to do synchronization between processes.
Reported failure: https://bugzilla.novell.com/show_bug.cgi?id=375897 Instead use a synchronization pipe to have the child thread send messages to the parent thread (with reasonable timeouts since this is testing blocking calls). # Apply to root of ltp-full-20081031 tree $ cd testcases/open_posix_testsuite/ $ make conformance/interfaces/mq_send/5-1.test $ conformance/interfaces/mq_send/5-1.test Signed-off-by: Brandon Philips <[EMAIL PROTECTED]> --- testcases/open_posix_testsuite/conformance/interfaces/mq_send/5-1.c | 53 +++--- testcases/open_posix_testsuite/include/posixtest.h | 81 ++++++++++ 2 files changed, 106 insertions(+), 28 deletions(-) Index: ltp-full-20081031/testcases/open_posix_testsuite/conformance/interfaces/mq_send/5-1.c =================================================================== --- ltp-full-20081031.orig/testcases/open_posix_testsuite/conformance/interfaces/mq_send/5-1.c +++ ltp-full-20081031/testcases/open_posix_testsuite/conformance/interfaces/mq_send/5-1.c @@ -42,14 +42,7 @@ char gqname[NAMESIZE]; mqd_t gqueue; -/* - * This handler is just used to catch the signal and stop sleep (so the - * parent knows the child is still busy sending signals). - */ -void stopsleep_handler(int signo) -{ - return; -} +int sync_pipes[2]; int main() { @@ -70,51 +63,55 @@ int main() return PTS_UNRESOLVED; } + if (sync_pipe_create(sync_pipes) == -1) { + perror("sync_pipe_create() did not return success"); + return PTS_UNRESOLVED; + } + if ((pid = fork()) == 0) { /* child here */ int i; - sleep(1); // give parent time to set up handler for (i=0; i<MAXMSG+1; i++) { mq_send(gqueue, msgptr, strlen(msgptr), 1); - /* send signal to parent each time message is sent */ - kill(getppid(), SIGABRT); + if (sync_pipe_notify(sync_pipes) < 0) { + perror("sync_pipe_notify() did not return success"); + return PTS_UNRESOLVED; + } } + } else { /* parent here */ struct sigaction act; - int j; + int j = 0; + int r; - /* parent runs stopsleep_handler when sleep is interrupted - by child */ - act.sa_handler=stopsleep_handler; - act.sa_flags=0; - sigemptyset(&act.sa_mask); - sigaction(SIGABRT, &act, 0); - - for (j=0; j<MAXMSG+1; j++) { // "infinite" loop - if (sleep(3) == 0) { - /* If sleep finished, child is probably blocking */ - break; + /* wait for child to reach MAXMSG */ + for (j = 0; j < MAXMSG; j++) { + /* set a long timeout since we are expecting success */ + if (sync_pipe_wait_select(sync_pipes, 60) != 0) { + printf("sync_pipe_wait\n"); + return PTS_FAIL; } } - if (j == MAXMSG+1) { + /* if we don't timeout here then we got too many messages, child never blocked */ + if (sync_pipe_wait_select(sync_pipes, 2) != -ETIMEDOUT) { printf("Child never blocked\n"); kill(pid, SIGKILL); //kill child return PTS_FAIL; } - /* receive message and allow blocked send to complete */ + /* receive one message and allow child's mq_send to complete */ if (mq_receive(gqueue, msgrcd, BUFFER, &pri) == -1) { perror("mq_receive() did not return success"); unresolved = 1; } - if (sleep(3) == 0) { + /* child has 5 seconds to call mq_send() again and notify us */ + if (sync_pipe_wait_select(sync_pipes, 5) == -ETIMEDOUT) { /* - * mq_send didn't succeed and interrupt sleep() - * with a signal + * mq_send didn't unblock */ kill(pid, SIGKILL); //kill child printf("mq_send() didn't appear to complete\n"); Index: ltp-full-20081031/testcases/open_posix_testsuite/include/posixtest.h =================================================================== --- ltp-full-20081031.orig/testcases/open_posix_testsuite/include/posixtest.h +++ ltp-full-20081031/testcases/open_posix_testsuite/include/posixtest.h @@ -14,3 +14,84 @@ #define PTS_UNRESOLVED 2 #define PTS_UNSUPPORTED 4 #define PTS_UNTESTED 5 + +#include <sys/select.h> + + +int sync_pipe_create(int fd[]) +{ + return pipe (fd); +} + +int sync_pipe_close(int fd[]) +{ + int r = 0; + + if (fd[0] != -1) + r = close (fd[0]); + if (fd[1] != -1) + r |= close (fd[1]); + return r; +} + +int sync_pipe_wait(int fd[]) +{ + char buf; + int r; + + if (fd[1] != -1) { + close (fd[1]); + fd[1] = -1; + } + + r = read (fd[0], &buf, 1); + + if ((r != 1) || (buf != 'A')) + return -1; + return 0; +} + +int sync_pipe_wait_select(int fd[], long tv_sec) +{ + char buf; + int r; + fd_set rfds; + struct timeval tv; + + tv.tv_sec = tv_sec; + tv.tv_usec = 0; + + if (fd[1] != -1) { + close (fd[1]); + fd[1] = -1; + } + + FD_ZERO(&rfds); + FD_SET(fd[0], &rfds); + + r = select(fd[0] + 1, &rfds, NULL, NULL, &tv); + + if (FD_ISSET(fd[0], &rfds)) { + return sync_pipe_wait(fd); + } + + return -ETIMEDOUT; +} + + +int sync_pipe_notify(int fd[]) +{ + char buf = 'A'; + int r; + + if (fd[0] != -1) { + close (fd[0]); + fd[0] = -1; + } + + r = write (fd[1], &buf, 1); + + if (r != 1) + return -1; + return 0; +} ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ _______________________________________________ Ltp-list mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ltp-list
