winpr/synch: fix ResetEvent & improve CTest
authorNorbert Federa <norbert.federa@thincast.com>
Wed, 17 Jun 2015 12:13:28 +0000 (14:13 +0200)
committerNorbert Federa <norbert.federa@thincast.com>
Wed, 17 Jun 2015 12:13:28 +0000 (14:13 +0200)
Unless there is an invalid parameter or internal error, ResetEvent
must return TRUE, even if the object is in nonsignaled state.

Also fixed and improved the CTest TestSynchEvent to test for the
expected/correct SetEvent and ResetEvent return values.

winpr/libwinpr/synch/event.c
winpr/libwinpr/synch/test/TestSynchEvent.c

index 6b61765..0157c65 100644 (file)
 
 #ifdef HAVE_EVENTFD_H
 #include <sys/eventfd.h>
-#include <errno.h>
 #endif
 
+#include <errno.h>
+
 #include "../handle/handle.h"
 #include "../pipe/pipe.h"
 
@@ -219,7 +220,6 @@ BOOL SetEvent(HANDLE hEvent)
 
                status = (length == 0) ? TRUE : FALSE;
 #else
-
                if (WaitForSingleObject(hEvent, 0) != WAIT_OBJECT_0)
                {
                        length = write(event->pipe_fd[1], "-", 1);
@@ -243,36 +243,29 @@ BOOL ResetEvent(HANDLE hEvent)
        ULONG Type;
        PVOID Object;
        int length;
-       BOOL status;
+       BOOL status = TRUE;
        WINPR_EVENT* event;
-       status = FALSE;
 
-       if (winpr_Handle_GetInfo(hEvent, &Type, &Object))
-       {
-               event = (WINPR_EVENT*) Object;
+       if (!winpr_Handle_GetInfo(hEvent, &Type, &Object))
+               return FALSE;
+
+       event = (WINPR_EVENT*) Object;
 
-               while (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
+       while (status && WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
+       {
+               do
                {
 #ifdef HAVE_EVENTFD_H
                        eventfd_t value;
-
-                       do
-                       {
-                               length = eventfd_read(event->pipe_fd[0], &value);
-                       }
-                       while ((length < 0) && (errno == EINTR));
-
-                       if ((length > 0) && (!status))
-                               status = TRUE;
-
+                       length = eventfd_read(event->pipe_fd[0], &value);
 #else
                        length = read(event->pipe_fd[0], &length, 1);
-
-                       if ((length == 1) && (!status))
-                               status = TRUE;
-
 #endif
                }
+               while ((length < 0) && (errno == EINTR));
+
+               if (length < 0)
+                       status = FALSE;
        }
 
        return status;
index 1262613..3f65065 100644 (file)
@@ -5,6 +5,19 @@
 int TestSynchEvent(int argc, char* argv[])
 {
        HANDLE event;
+       int i;
+
+       if (ResetEvent(NULL))
+       {
+               printf("ResetEvent(NULL) unexpectedly succeeded\n");
+               return -1;
+       }
+
+       if (SetEvent(NULL))
+       {
+               printf("SetEvent(NULL) unexpectedly succeeded\n");
+               return -1;
+       }
 
        event = CreateEvent(NULL, TRUE, TRUE, NULL);
 
@@ -16,23 +29,62 @@ int TestSynchEvent(int argc, char* argv[])
 
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
        {
-               printf("WaitForSingleObject(event, INFINITE) failure\n");
+               printf("WaitForSingleObject failure 1\n");
                return -1;
        }
 
-       ResetEvent(event);
+       if (!ResetEvent(event))
+       {
+               printf("ResetEvent failure with signaled event object\n");
+               return -1;
+       }
 
        if (WaitForSingleObject(event, 0) != WAIT_TIMEOUT)
        {
-               printf("WaitForSingleObject(event, 0) failure\n");
+               printf("WaitForSingleObject failure 2\n");
                return -1;
        }
 
-       SetEvent(event);
+       if (!ResetEvent(event))
+       {
+               /* Note: ResetEvent must also succeed if event is currently nonsignaled */
+               printf("ResetEvent failure with nonsignaled event object\n");
+               return -1;
+       }
+
+       if (!SetEvent(event))
+       {
+               printf("SetEvent failure with nonsignaled event object\n");
+               return -1;
+       }
 
        if (WaitForSingleObject(event, 0) != WAIT_OBJECT_0)
        {
-               printf("WaitForSingleObject(event, 0) failure\n");
+               printf("WaitForSingleObject failure 3\n");
+               return -1;
+       }
+
+       for (i = 0; i < 10000; i++)
+       {
+               if (!SetEvent(event))
+               {
+                       printf("SetEvent failure with signaled event object (i = %d)\n", i);
+                       return -1;
+               }
+       }
+
+       if (!ResetEvent(event))
+       {
+               printf("ResetEvent failure after multiple SetEvent calls\n");
+               return -1;
+       }
+
+       /* Independent of the amount of the previous SetEvent calls, a single
+          ResetEvent must be sufficient to get into nonsignaled state */
+
+       if (WaitForSingleObject(event, 0) != WAIT_TIMEOUT)
+       {
+               printf("WaitForSingleObject failure 4\n");
                return -1;
        }