Version 2: The test failed a few hours after I sent this off. I think it
was caused by a pid collision which caused the test to use the same
queue as an earlier failed test that didn't close out its queue. This
version of the test uses O_EXCL to avoid this. And it cleans up the
queue on every failure case.

This test was racy. It relied on signals interrupting sleeps to do
syncronization between processes. It also didn't cleanup the queue on
the failure cases and assumed that its queue didn't already exist. This
patch fixes these issues.

Reported failures: https://bugzilla.novell.com/show_bug.cgi?id=375897

Instead use a syncronization 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 |   84 
+++++-----
 testcases/open_posix_testsuite/include/posixtest.h                  |   83 
+++++++++
 2 files changed, 130 insertions(+), 37 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
@@ -1,6 +1,10 @@
 /*
  * Copyright (c) 2002, Intel Corporation. All rights reserved.
+ * Copyright (c) 2008, Novell Inc. All rights reserved.
+ *
  * Created by:  julie.n.fleischer REMOVE-THIS AT intel DOT com
+ * Major fixes by: Brandon Philips <[EMAIL PROTECTED]>
+ *
  * This file is licensed under the GPL license.  For the full content
  * of this license, see the COPYING file at the top level of this
  * source tree.
@@ -42,13 +46,19 @@
 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)
+int sync_pipes[2];
+
+int cleanup_for_exit(int gqueue, char *gqname, int ret)
 {
-       return;
+       mq_close(gqueue);
+       mq_unlink(gqname);
+
+       if (ret == PTS_PASS)
+               printf("Test PASSED\n");
+       else if (ret == PTS_FAIL)
+               printf("Test FAILED\n");
+
+       return ret;
 }
 
 int main()
@@ -64,70 +74,70 @@ int main()
 
        attr.mq_msgsize = BUFFER;
        attr.mq_maxmsg = MAXMSG;
-        gqueue = mq_open(gqname, O_CREAT |O_RDWR, S_IRUSR | S_IWUSR, &attr);
+
+       /* Use O_CREAT + O_EXCL to avoid using a previously created queue */
+        gqueue = mq_open(gqname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR, 
&attr);
         if (gqueue == (mqd_t)-1) {
-                perror("mq_open() did not return success");
+               perror("mq_open() did not return success");
                 return PTS_UNRESOLVED;
         }
 
+       if (sync_pipe_create(sync_pipes) == -1) {
+               perror("sync_pipe_create() did not return success");
+               return cleanup_for_exit(gqueue, gqname, 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);
+                       mq_send(gqueue, msgptr, strlen(msgptr), 1);
+
+                       if (sync_pipe_notify(sync_pipes) < 0) {
+                               perror("sync_pipe_notify() did not return 
success");
+                               return cleanup_for_exit(gqueue, gqname, 
PTS_UNRESOLVED);
+                       }
                }
        } else {
                /* parent here */
                struct sigaction act;
                int j;
+               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 cleanup_for_exit(gqueue, gqname, 
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, 1) != -ETIMEDOUT) {
                        printf("Child never blocked\n");
                        kill(pid, SIGKILL); //kill child
-                       return PTS_FAIL;
+                       return cleanup_for_exit(gqueue, gqname, 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");
-                       mq_close(gqueue);
-                       mq_unlink(gqname);
-                        printf("Test FAILED\n");
-                        return PTS_FAIL;
+                       return cleanup_for_exit(gqueue, gqname, PTS_FAIL);
                 }
 
-               mq_close(gqueue);
-               mq_unlink(gqname);
-               printf("Test PASSED\n");
-               return PTS_PASS;
+               return cleanup_for_exit(gqueue, gqname, PTS_PASS);
        }
 
        return PTS_UNRESOLVED;
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,86 @@
 #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;
+       int err;
+
+       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);
+       err = errno;
+
+       if (FD_ISSET(fd[0], &rfds)) {
+               return sync_pipe_wait(fd);
+       }
+
+       return r ? err : -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;
+}

------------------------------------------------------------------------------
SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada.
The future of the web can't happen without you.  Join us at MIX09 to help
pave the way to the Next Web now. Learn more and register at
http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to