apr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From minf...@apache.org
Subject svn commit: r899905 - in /apr/apr/trunk: include/ include/arch/unix/ poll/unix/ test/
Date Sat, 16 Jan 2010 08:53:40 GMT
Author: minfrin
Date: Sat Jan 16 08:53:33 2010
New Revision: 899905

URL: http://svn.apache.org/viewvc?rev=899905&view=rev
Log:
* Add apr_pollcb_wakeup(), with similar behavior to
apr_pollset_wakeup(). Along the way, refactor the code for
creating/managing the wakeup pipe to a separate file, wakeup.c

* Add apr_pollcb_method_name(), with similar behavior to
apr_pollset_method_name()

* Add minimal unit tests for apr_pollset_wakeup() and apr_pollcb_wakeup()

apr_pollcb_wakeup() is supported with all the poll methods supported
by pollcb (kqueue, epoll, poll, and event ports).
Submitted by: Neil Conway <nrc@cs.berkeley.edu>

Added:
    apr/apr/trunk/poll/unix/wakeup.c
Modified:
    apr/apr/trunk/include/apr_poll.h
    apr/apr/trunk/include/arch/unix/apr_arch_poll_private.h
    apr/apr/trunk/poll/unix/epoll.c
    apr/apr/trunk/poll/unix/kqueue.c
    apr/apr/trunk/poll/unix/poll.c
    apr/apr/trunk/poll/unix/pollcb.c
    apr/apr/trunk/poll/unix/pollset.c
    apr/apr/trunk/poll/unix/port.c
    apr/apr/trunk/poll/unix/select.c
    apr/apr/trunk/test/testpoll.c

Modified: apr/apr/trunk/include/apr_poll.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/apr_poll.h?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/include/apr_poll.h (original)
+++ apr/apr/trunk/include/apr_poll.h Sat Jan 16 08:53:33 2010
@@ -61,7 +61,7 @@
                                       * are not copied
                                       */
 #define APR_POLLSET_WAKEABLE   0x004 /**< Poll operations are interruptable by
-                                      * apr_pollset_wakeup()
+                                      * apr_pollset_wakeup() or apr_pollcb_wakeup()
                                       */
 #define APR_POLLSET_NODEFAULT  0x010 /**< Do not try to use the default method if
                                       * the specified non-default method cannot be
@@ -131,7 +131,7 @@
  * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollset is
  *         created with an additional internal pipe object used for the
  *         apr_pollset_wakeup() call. The actual size of pollset is
- *         in that case size + 1. This feature is only supported on some
+ *         in that case @a size + 1. This feature is only supported on some
  *         platforms; the apr_pollset_create() call will fail with
  *         APR_ENOTIMPL on platforms where it is not supported.
  * @remark If flags contains APR_POLLSET_NOCOPY, then the apr_pollfd_t
@@ -226,6 +226,7 @@
  * Remove a descriptor from a pollset
  * @param pollset The pollset from which to remove the descriptor
  * @param descriptor The descriptor to remove
+ * @remark If the descriptor is not found, APR_NOTFOUND is returned.
  * @remark If the pollset has been created with APR_POLLSET_THREADSAFE
  *         and thread T1 is blocked in a call to apr_pollset_poll() for
  *         this same pollset that is being modified via apr_pollset_remove()
@@ -305,7 +306,7 @@
  */
 APR_DECLARE(const char *) apr_poll_method_defname(void);
 
-/** Opaque structure used for pollset API */
+/** Opaque structure used for pollcb API */
 typedef struct apr_pollcb_t apr_pollcb_t;
 
 /**
@@ -315,8 +316,12 @@
  * @param p The pool from which to allocate the pollcb
  * @param flags Optional flags to modify the operation of the pollcb.
  *
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollcb is
+ *         created with an additional internal pipe object used for the
+ *         apr_pollcb_wakeup() call. The actual size of pollcb is
+ *         in that case @a size + 1.
  * @remark Pollcb is only supported on some platforms; the apr_pollcb_create()
- * call will fail with APR_ENOTIMPL on platforms where it is not supported.
+ *         call will fail with APR_ENOTIMPL on platforms where it is not supported.
  */
 APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
                                             apr_uint32_t size,
@@ -333,8 +338,12 @@
  *         method cannot be used, the default method will be used unless the
  *         APR_POLLSET_NODEFAULT flag has been specified.
  *
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollcb is
+ *         created with an additional internal pipe object used for the
+ *         apr_pollcb_wakeup() call. The actual size of pollcb is
+ *         in that case @a size + 1.
  * @remark Pollcb is only supported on some platforms; the apr_pollcb_create_ex()
- * call will fail with APR_ENOTIMPL on platforms where it is not supported.
+ *         call will fail with APR_ENOTIMPL on platforms where it is not supported.
  */
 APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **pollcb,
                                                apr_uint32_t size,
@@ -365,6 +374,7 @@
  * Remove a descriptor from a pollcb
  * @param pollcb The pollcb from which to remove the descriptor
  * @param descriptor The descriptor to remove
+ * @remark If the descriptor is not found, APR_NOTFOUND is returned.
  * @remark apr_pollcb_remove() cannot be used to remove a subset of requested
  *         events for a descriptor.  The reqevents field in the apr_pollfd_t
  *         parameter must contain the same value when removing as when adding.
@@ -372,11 +382,14 @@
 APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
                                             apr_pollfd_t *descriptor);
 
-/** Function prototype for pollcb handlers 
+/**
+ * Function prototype for pollcb handlers 
  * @param baton Opaque baton passed into apr_pollcb_poll()
- * @param descriptor Contains the notification for an active descriptor, 
- *                   the rtnevents member contains what events were triggered
+ * @param descriptor Contains the notification for an active descriptor. 
+ *                   The @a rtnevents member describes which events were triggered
  *                   for this descriptor.
+ * @remark If the pollcb handler does not return APR_SUCCESS, the apr_pollcb_poll()
+ *         call returns with the handler's return value.
  */
 typedef apr_status_t (*apr_pollcb_cb_t)(void *baton, apr_pollfd_t *descriptor);
 
@@ -387,17 +400,34 @@
  *                maximum, not a minimum.  If a descriptor is signalled, the
  *                function will return before this time.  If timeout is
  *                negative, the function will block until a descriptor is
- *                signalled.
+ *                signalled or until apr_pollcb_wakeup() has been called.
  * @param func Callback function to call for each active descriptor.
  * @param baton Opaque baton passed to the callback function.
  * @remark Multiple signalled conditions for the same descriptor may be reported
  *         in one or more calls to the callback function, depending on the
  *         implementation.
+ * @remark APR_EINTR will be returned if the pollset has been created with
+ *         APR_POLLSET_WAKEABLE and apr_pollcb_wakeup() has been called while
+ *         waiting for activity.
  */
 APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
                                           apr_interval_time_t timeout,
                                           apr_pollcb_cb_t func,
-                                          void *baton); 
+                                          void *baton);
+
+/**
+ * Interrupt the blocked apr_pollcb_poll() call.
+ * @param pollcb The pollcb to use
+ * @remark If the pollcb was not created with APR_POLLSET_WAKEABLE the
+ *         return value is APR_EINIT.
+ */
+APR_DECLARE(apr_status_t) apr_pollcb_wakeup(apr_pollcb_t *pollcb);
+
+/**
+ * Return a printable representation of the pollcb method.
+ * @param pollcb The pollcb to use
+ */
+APR_DECLARE(const char *) apr_pollcb_method_name(apr_pollcb_t *pollcb);
 
 /** @} */
 

Modified: apr/apr/trunk/include/arch/unix/apr_arch_poll_private.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/unix/apr_arch_poll_private.h?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/include/arch/unix/apr_arch_poll_private.h (original)
+++ apr/apr/trunk/include/arch/unix/apr_arch_poll_private.h Sat Jan 16 08:53:33 2010
@@ -139,6 +139,10 @@
     apr_pool_t *pool;
     apr_uint32_t nelts;
     apr_uint32_t nalloc;
+    apr_uint32_t flags;
+    /* Pipe descriptors used for wakeup */
+    apr_file_t *wakeup_pipe[2];
+    apr_pollfd_t wakeup_pfd;
     int fd;
     apr_pollcb_pset pollset;
     apr_pollfd_t **copyset;
@@ -159,10 +163,13 @@
     apr_status_t (*add)(apr_pollcb_t *, apr_pollfd_t *);
     apr_status_t (*remove)(apr_pollcb_t *, apr_pollfd_t *);
     apr_status_t (*poll)(apr_pollcb_t *, apr_interval_time_t, apr_pollcb_cb_t, void *);
+    apr_status_t (*cleanup)(apr_pollcb_t *);
     const char *name;
 };
 
 /* Private functions */
-void apr_pollset_drain_wakeup_pipe(apr_pollset_t *pollset);
+apr_status_t create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd, apr_file_t **wakeup_pipe);
+apr_status_t close_wakeup_pipe(apr_file_t **wakeup_pipe);
+void drain_wakeup_pipe(apr_file_t **wakeup_pipe);
 
 #endif /* APR_ARCH_POLL_PRIVATE_H */

Modified: apr/apr/trunk/poll/unix/epoll.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/poll/unix/epoll.c?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/poll/unix/epoll.c (original)
+++ apr/apr/trunk/poll/unix/epoll.c Sat Jan 16 08:53:33 2010
@@ -147,7 +147,7 @@
                                      const apr_pollfd_t *descriptor)
 {
     struct epoll_event ev = {0};
-    int ret = -1;
+    int ret;
     pfd_elem_t *elem = NULL;
     apr_status_t rv = APR_SUCCESS;
 
@@ -204,7 +204,7 @@
     struct epoll_event ev = {0}; /* ignored, but must be passed with
                                   * kernel < 2.6.9
                                   */
-    int ret = -1;
+    int ret;
 
     if (descriptor->desc_type == APR_POLL_SOCKET) {
         ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL,
@@ -245,9 +245,8 @@
                                            apr_int32_t *num,
                                            const apr_pollfd_t **descriptors)
 {
-    int ret, i, j;
+    int ret;
     apr_status_t rv = APR_SUCCESS;
-    apr_pollfd_t *fdptr;
 
     if (timeout > 0) {
         timeout /= 1000;
@@ -264,6 +263,9 @@
         rv = APR_TIMEUP;
     }
     else {
+        int i, j;
+        apr_pollfd_t *fdptr;
+
         for (i = 0, j = 0; i < ret; i++) {
             if (pollset->flags & APR_POLLSET_NOCOPY) {
                 fdptr = (apr_pollfd_t *)(pollset->p->pollset[i].data.ptr);
@@ -277,7 +279,7 @@
             if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
                 fdptr->desc_type == APR_POLL_FILE &&
                 fdptr->desc.f == pollset->wakeup_pipe[0]) {
-                apr_pollset_drain_wakeup_pipe(pollset);
+                drain_wakeup_pipe(pollset->wakeup_pipe);
                 rv = APR_EINTR;
             }
             else {
@@ -319,9 +321,8 @@
 
 apr_pollset_provider_t *apr_pollset_provider_epoll = &impl;
 
-static apr_status_t cb_cleanup(void *p_)
+static apr_status_t impl_pollcb_cleanup(apr_pollcb_t *pollcb)
 {
-    apr_pollcb_t *pollcb = (apr_pollcb_t *) p_;
     close(pollcb->fd);
     return APR_SUCCESS;
 }
@@ -358,7 +359,6 @@
     
     pollcb->fd = fd;
     pollcb->pollset.epoll = apr_palloc(p, size * sizeof(struct epoll_event));
-    apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null);
 
     return APR_SUCCESS;
 }
@@ -370,7 +370,7 @@
     int ret;
     
     ev.events = get_epoll_event(descriptor->reqevents);
-    ev.data.ptr = (void *)descriptor;
+    ev.data.ptr = (void *) descriptor;
 
     if (descriptor->desc_type == APR_POLL_SOCKET) {
         ret = epoll_ctl(pollcb->fd, EPOLL_CTL_ADD,
@@ -395,7 +395,7 @@
     struct epoll_event ev = {0}; /* ignored, but must be passed with
                                   * kernel < 2.6.9
                                   */
-    int ret = -1;
+    int ret;
     
     if (descriptor->desc_type == APR_POLL_SOCKET) {
         ret = epoll_ctl(pollcb->fd, EPOLL_CTL_DEL,
@@ -437,6 +437,14 @@
     else {
         for (i = 0; i < ret; i++) {
             apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.epoll[i].data.ptr);
+
+            if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
+                pollfd->desc_type == APR_POLL_FILE &&
+                pollfd->desc.f == pollcb->wakeup_pipe[0]) {
+                drain_wakeup_pipe(pollcb->wakeup_pipe);
+                return APR_EINTR;
+            }
+
             pollfd->rtnevents = get_epoll_revent(pollcb->pollset.epoll[i].events);
 
             rv = func(baton, pollfd);
@@ -454,6 +462,7 @@
     impl_pollcb_add,
     impl_pollcb_remove,
     impl_pollcb_poll,
+    impl_pollcb_cleanup,
     "epoll"
 };
 

Modified: apr/apr/trunk/poll/unix/kqueue.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/poll/unix/kqueue.c?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/poll/unix/kqueue.c (original)
+++ apr/apr/trunk/poll/unix/kqueue.c Sat Jan 16 08:53:33 2010
@@ -246,7 +246,7 @@
                                       apr_int32_t *num,
                                       const apr_pollfd_t **descriptors)
 {
-    int ret, i, j;
+    int ret;
     struct timespec tv, *tvptr;
     apr_status_t rv = APR_SUCCESS;
     apr_pollfd_t fd;
@@ -270,12 +270,14 @@
         rv = APR_TIMEUP;
     }
     else {
+        int i, j;
+
         for (i = 0, j = 0; i < ret; i++) {
-            fd = (((pfd_elem_t*)(pollset->p->ke_set[i].udata))->pfd);
+            fd = (((pfd_elem_t *)(pollset->p->ke_set[i].udata))->pfd);
             if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
                 fd.desc_type == APR_POLL_FILE &&
                 fd.desc.f == pollset->wakeup_pipe[0]) {
-                apr_pollset_drain_wakeup_pipe(pollset);
+                drain_wakeup_pipe(pollset->wakeup_pipe);
                 rv = APR_EINTR;
             }
             else {
@@ -294,7 +296,6 @@
         }
     }
 
-
     pollset_lock_rings();
 
     /* Shift all PFDs in the Dead Ring to the Free Ring */
@@ -317,9 +318,8 @@
 
 apr_pollset_provider_t *apr_pollset_provider_kqueue = &impl;
 
-static apr_status_t cb_cleanup(void *b_)
+static apr_status_t impl_pollcb_cleanup(apr_pollcb_t *pollcb)
 {
-    apr_pollcb_t *pollcb = (apr_pollcb_t *) b_;
     close(pollcb->fd);
     return APR_SUCCESS;
 }
@@ -348,8 +348,7 @@
     }
  
     pollcb->fd = fd;
-    pollcb->pollset.ke = (struct kevent *)apr_pcalloc(p, 2 * size * sizeof(struct kevent));
-    apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null);
+    pollcb->pollset.ke = (struct kevent *) apr_pcalloc(p, 2 * size * sizeof(struct kevent));
     
     return APR_SUCCESS;
 }
@@ -452,7 +451,14 @@
     else {
         for (i = 0; i < ret; i++) {
             apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.ke[i].udata);
-            
+
+            if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
+                pollfd->desc_type == APR_POLL_FILE &&
+                pollfd->desc.f == pollcb->wakeup_pipe[0]) {
+                drain_wakeup_pipe(pollcb->wakeup_pipe);
+                return APR_EINTR;
+            }
+
             pollfd->rtnevents = get_kqueue_revent(pollcb->pollset.ke[i].filter,
                                                   pollcb->pollset.ke[i].flags);
             
@@ -472,6 +478,7 @@
     impl_pollcb_add,
     impl_pollcb_remove,
     impl_pollcb_poll,
+    impl_pollcb_cleanup,
     "kqueue"
 };
 

Modified: apr/apr/trunk/poll/unix/poll.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/poll/unix/poll.c?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/poll/unix/poll.c (original)
+++ apr/apr/trunk/poll/unix/poll.c Sat Jan 16 08:53:33 2010
@@ -240,7 +240,6 @@
 {
     int ret;
     apr_status_t rv = APR_SUCCESS;
-    apr_uint32_t i, j;
 
     if (timeout > 0) {
         timeout /= 1000;
@@ -258,6 +257,8 @@
         return APR_TIMEUP;
     }
     else {
+        apr_uint32_t i, j;
+
         for (i = 0, j = 0; i < pollset->nelts; i++) {
             if (pollset->p->pollset[i].revents != 0) {
                 /* Check if the polled descriptor is our
@@ -266,8 +267,8 @@
                 if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
                     pollset->p->query_set[i].desc_type == APR_POLL_FILE &&
                     pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0])
{
-                        apr_pollset_drain_wakeup_pipe(pollset);
-                        rv = APR_EINTR;
+                    drain_wakeup_pipe(pollset->wakeup_pipe);
+                    rv = APR_EINTR;
                 }
                 else {
                     pollset->p->result_set[j] = pollset->p->query_set[i];
@@ -305,7 +306,7 @@
                                        apr_uint32_t flags)
 {
 #if APR_HAS_THREADS
-  return APR_ENOTIMPL;
+    return APR_ENOTIMPL;
 #endif
 
     pollcb->fd = -1;
@@ -402,6 +403,14 @@
         for (i = 0; i < pollcb->nelts; i++) {
             if (pollcb->pollset.ps[i].revents != 0) {
                 apr_pollfd_t *pollfd = pollcb->copyset[i];
+
+                if ((pollcb->flags & APR_POLLSET_WAKEABLE) &&
+                    pollfd->desc_type == APR_POLL_FILE &&
+                    pollfd->desc.f == pollcb->wakeup_pipe[0]) {
+                    drain_wakeup_pipe(pollcb->wakeup_pipe);
+                    return APR_EINTR;
+                }
+
                 pollfd->rtnevents = get_revent(pollcb->pollset.ps[i].revents);    
               
                 rv = func(baton, pollfd);
                 if (rv) {
@@ -418,6 +427,7 @@
     impl_pollcb_add,
     impl_pollcb_remove,
     impl_pollcb_poll,
+    NULL,
     "poll"
 };
 

Modified: apr/apr/trunk/poll/unix/pollcb.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/poll/unix/pollcb.c?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/poll/unix/pollcb.c (original)
+++ apr/apr/trunk/poll/unix/pollcb.c Sat Jan 16 08:53:33 2010
@@ -72,6 +72,20 @@
     return provider;
 }
 
+static apr_status_t pollcb_cleanup(void *p)
+{
+    apr_pollcb_t *pollcb = (apr_pollcb_t *) p;
+
+    if (pollcb->provider->cleanup) {
+        (*pollcb->provider->cleanup)(pollcb);
+    }
+    if (pollcb->flags & APR_POLLSET_WAKEABLE) {
+        close_wakeup_pipe(pollcb->wakeup_pipe);
+    }
+
+    return APR_SUCCESS;
+}
+
 APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **ret_pollcb,
                                                apr_uint32_t size,
                                                apr_pool_t *p,
@@ -108,9 +122,15 @@
         }
     }
 
+    if (flags & APR_POLLSET_WAKEABLE) {
+        /* Add room for wakeup descriptor */
+        size++;
+    }
+
     pollcb = apr_palloc(p, sizeof(*pollcb));
     pollcb->nelts = 0;
     pollcb->nalloc = size;
+    pollcb->flags = flags;
     pollcb->pool = p;
     pollcb->provider = provider;
 
@@ -136,6 +156,21 @@
         pollcb->provider = provider;
     }
 
+    if (flags & APR_POLLSET_WAKEABLE) {
+        /* Create wakeup pipe */
+        if ((rv = create_wakeup_pipe(pollcb->pool, &pollcb->wakeup_pfd,
+                                     pollcb->wakeup_pipe)) != APR_SUCCESS) {
+            return rv;
+        }
+
+        if ((rv = apr_pollcb_add(pollcb, &pollcb->wakeup_pfd)) != APR_SUCCESS) {
+            return rv;
+        }
+    }
+    if ((flags & APR_POLLSET_WAKEABLE) || provider->cleanup)
+        apr_pool_cleanup_register(p, pollcb, pollcb_cleanup,
+                                  apr_pool_cleanup_null);
+
     *ret_pollcb = pollcb;
     return APR_SUCCESS;
 }
@@ -169,3 +204,16 @@
 {
     return (*pollcb->provider->poll)(pollcb, timeout, func, baton);
 }
+
+APR_DECLARE(apr_status_t) apr_pollcb_wakeup(apr_pollcb_t *pollcb)
+{
+    if (pollcb->flags & APR_POLLSET_WAKEABLE)
+        return apr_file_putc(1, pollcb->wakeup_pipe[1]);
+    else
+        return APR_EINIT;
+}
+
+APR_DECLARE(const char *) apr_pollcb_method_name(apr_pollcb_t *pollcb)
+{
+    return pollcb->provider->name;
+}

Modified: apr/apr/trunk/poll/unix/pollset.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/poll/unix/pollset.c?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/poll/unix/pollset.c (original)
+++ apr/apr/trunk/poll/unix/pollset.c Sat Jan 16 08:53:33 2010
@@ -30,140 +30,6 @@
 
 static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD;
 
-#if !APR_FILES_AS_SOCKETS
-
-#ifdef WIN32
-
-/* Create a dummy wakeup socket pipe for interrupting the poller
- */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
-{
-    apr_status_t rv;
-    apr_pollfd_t fd;
-
-    if ((rv = file_socket_pipe_create(&pollset->wakeup_pipe[0],
-                                      &pollset->wakeup_pipe[1],
-                                      pollset->pool)) != APR_SUCCESS)
-        return rv;
-    fd.reqevents = APR_POLLIN;
-    fd.desc_type = APR_POLL_FILE;
-    fd.desc.f = pollset->wakeup_pipe[0];
-    /* Add the pipe to the pollset
-     */
-    return apr_pollset_add(pollset, &fd);
-}
-
-static apr_status_t close_wakeup_pipe(apr_pollset_t *pollset)
-{
-    apr_status_t rv0 = APR_SUCCESS;
-    apr_status_t rv1 = APR_SUCCESS;
-
-    /* Close both sides of the wakeup pipe */
-    if (pollset->wakeup_pipe[0]) {
-        rv0 = file_socket_pipe_close(pollset->wakeup_pipe[0]);
-        pollset->wakeup_pipe[0] = NULL;
-    }
-    if (pollset->wakeup_pipe[1]) {
-        rv1 = file_socket_pipe_close(pollset->wakeup_pipe[1]);
-        pollset->wakeup_pipe[1] = NULL;
-    }
-    return rv0 ? rv0 : rv1;
-}
-
-#else /* !WIN32 */
-
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
-{
-    return APR_ENOTIMPL;
-}
-
-static apr_status_t close_wakeup_pipe(apr_pollset_t *pollset)
-{
-    return APR_ENOTIMPL;
-}
-
-#endif /* !WIN32 */
-
-#else  /* APR_FILES_AS_SOCKETS */
-
-/* Create a dummy wakeup pipe for interrupting the poller
- */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
-{
-    apr_status_t rv;
-    apr_pollfd_t fd;
-
-    if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0],
-                                   &pollset->wakeup_pipe[1],
-                                   pollset->pool)) != APR_SUCCESS)
-        return rv;
-    fd.reqevents = APR_POLLIN;
-    fd.desc_type = APR_POLL_FILE;
-    fd.desc.f = pollset->wakeup_pipe[0];
-
-    {
-        int flags;
-
-        if ((flags = fcntl(pollset->wakeup_pipe[0]->filedes, F_GETFD)) == -1)
-            return errno;
-
-        flags |= FD_CLOEXEC;
-        if (fcntl(pollset->wakeup_pipe[0]->filedes, F_SETFD, flags) == -1)
-            return errno;
-    }
-    {
-        int flags;
-
-        if ((flags = fcntl(pollset->wakeup_pipe[1]->filedes, F_GETFD)) == -1)
-            return errno;
-
-        flags |= FD_CLOEXEC;
-        if (fcntl(pollset->wakeup_pipe[1]->filedes, F_SETFD, flags) == -1)
-            return errno;
-    }
-
-    /* Add the pipe to the pollset
-     */
-    return apr_pollset_add(pollset, &fd);
-}
-
-static apr_status_t close_wakeup_pipe(apr_pollset_t *pollset)
-{
-    apr_status_t rv0;
-    apr_status_t rv1;
-
-    /* Close both sides of the wakeup pipe */
-    if (pollset->wakeup_pipe[0]) {
-        rv0 = apr_file_close(pollset->wakeup_pipe[0]);
-        pollset->wakeup_pipe[0] = NULL;
-    }
-    if (pollset->wakeup_pipe[1]) {
-        rv1 = apr_file_close(pollset->wakeup_pipe[1]);
-        pollset->wakeup_pipe[1] = NULL;
-    }
-    return rv0 ? rv0 : rv1;
-}
-
-#endif /* APR_FILES_AS_SOCKETS */
-
-/* Read and discard what's ever in the wakeup pipe.
- */
-void apr_pollset_drain_wakeup_pipe(apr_pollset_t *pollset)
-{
-    char rb[512];
-    apr_size_t nr = sizeof(rb);
-
-    while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
-        /* Although we write just one byte to the other end of the pipe
-         * during wakeup, multiple treads could call the wakeup.
-         * So simply drain out from the input side of the pipe all
-         * the data.
-         */
-        if (nr != sizeof(rb))
-            break;
-    }
-}
-
 static apr_status_t pollset_cleanup(void *p)
 {
     apr_pollset_t *pollset = (apr_pollset_t *) p;
@@ -171,7 +37,7 @@
         (*pollset->provider->cleanup)(pollset);
     }
     if (pollset->flags & APR_POLLSET_WAKEABLE) {
-        close_wakeup_pipe(pollset);
+        close_wakeup_pipe(pollset->wakeup_pipe);
     }
 
     return APR_SUCCESS;
@@ -287,8 +153,15 @@
         pollset->provider = provider;
     }
     if (flags & APR_POLLSET_WAKEABLE) {
+        apr_pollfd_t pfd;
+
         /* Create wakeup pipe */
-        if ((rv = create_wakeup_pipe(pollset)) != APR_SUCCESS) {
+        if ((rv = create_wakeup_pipe(pollset->pool, &pfd,
+                                     pollset->wakeup_pipe)) != APR_SUCCESS) {
+            return rv;
+        }
+
+        if ((rv = apr_pollset_add(pollset, &pfd)) != APR_SUCCESS) {
             return rv;
         }
     }

Modified: apr/apr/trunk/poll/unix/port.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/poll/unix/port.c?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/poll/unix/port.c (original)
+++ apr/apr/trunk/poll/unix/port.c Sat Jan 16 08:53:33 2010
@@ -405,7 +405,7 @@
             if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
                 fp.desc_type == APR_POLL_FILE &&
                 fp.desc.f == pollset->wakeup_pipe[0]) {
-                apr_pollset_drain_wakeup_pipe(pollset);
+                drain_wakeup_pipe(pollset->wakeup_pipe);
                 rv = APR_EINTR;
             }
             else {
@@ -458,9 +458,8 @@
 
 apr_pollset_provider_t *apr_pollset_provider_port = &impl;
 
-static apr_status_t cb_cleanup(void *p_)
+static apr_status_t impl_pollcb_cleanup(apr_pollcb_t *pollcb)
 {
-    apr_pollcb_t *pollcb = (apr_pollcb_t *) p_;
     close(pollcb->fd);
     return APR_SUCCESS;
 }
@@ -488,7 +487,6 @@
     }
 
     pollcb->pollset.port = apr_palloc(p, size * sizeof(port_event_t));
-    apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null);
 
     return APR_SUCCESS;
 }
@@ -541,16 +539,25 @@
                                      apr_pollcb_cb_t func,
                                      void *baton)
 {
-    apr_pollfd_t *pollfd;
     apr_status_t rv;
-    unsigned int i, nget = 1;
+    unsigned int nget = 1;
 
     rv = call_port_getn(pollcb->fd, pollcb->pollset.port, pollcb->nalloc,
                         &nget, timeout);
 
     if (nget) {
+        unsigned int i;
+
         for (i = 0; i < nget; i++) {
-            pollfd = (apr_pollfd_t *)(pollcb->pollset.port[i].portev_user);
+            apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.port[i].portev_user);
+
+            if ((pollfd->flags & APR_POLLSET_WAKEABLE) &&
+                pollfd->desc_type == APR_POLL_FILE &&
+                pollfd->desc.f == pollfd->wakeup_pipe[0]) {
+                drain_wakeup_pipe(pollfd->wakeup_pipe);
+                return APR_EINTR;
+            }
+
             pollfd->rtnevents = get_revent(pollcb->pollset.port[i].portev_events);
 
             rv = func(baton, pollfd);
@@ -569,6 +576,7 @@
     impl_pollcb_add,
     impl_pollcb_remove,
     impl_pollcb_poll,
+    impl_pollcb_cleanup,
     "port"
 };
 

Modified: apr/apr/trunk/poll/unix/select.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/poll/unix/select.c?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/poll/unix/select.c (original)
+++ apr/apr/trunk/poll/unix/select.c Sat Jan 16 08:53:33 2010
@@ -382,7 +382,7 @@
         else {
             if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
                 pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
-                apr_pollset_drain_wakeup_pipe(pollset);
+                drain_wakeup_pipe(pollset->wakeup_pipe);
                 rv = APR_EINTR;
                 continue;
             }

Added: apr/apr/trunk/poll/unix/wakeup.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/poll/unix/wakeup.c?rev=899905&view=auto
==============================================================================
--- apr/apr/trunk/poll/unix/wakeup.c (added)
+++ apr/apr/trunk/poll/unix/wakeup.c Sat Jan 16 08:53:33 2010
@@ -0,0 +1,151 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
+#include "apr_arch_inherit.h"
+
+#if !APR_FILES_AS_SOCKETS
+
+#ifdef WIN32
+
+apr_status_t create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd,
+                                apr_file_t **wakeup_pipe)
+{
+    apr_status_t rv;
+
+    if ((rv = file_socket_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1],
+                                      pool)) != APR_SUCCESS)
+        return rv;
+
+    pfd->reqevents = APR_POLLIN;
+    pfd->desc_type = APR_POLL_FILE;
+    pfd->desc.f = wakeup_pipe[0];
+    return APR_SUCCESS;
+}
+
+apr_status_t close_wakeup_pipe(apr_file_t **wakeup_pipe)
+{
+    apr_status_t rv0 = APR_SUCCESS;
+    apr_status_t rv1 = APR_SUCCESS;
+
+    /* Close both sides of the wakeup pipe */
+    if (wakeup_pipe[0]) {
+        rv0 = file_socket_pipe_close(wakeup_pipe[0]);
+        wakeup_pipe[0] = NULL;
+    }
+    if (wakeup_pipe[1]) {
+        rv1 = file_socket_pipe_close(wakeup_pipe[1]);
+        wakeup_pipe[1] = NULL;
+    }
+    return rv0 ? rv0 : rv1
+}
+
+#else /* !WIN32 */
+
+apr_status_t create_wakeup_pipe(apr_pollfd_t *pfd, apr_file_t **wakeup_pipe)
+{
+    return APR_ENOTIMPL;
+}
+
+apr_status_t close_wakeup_pipe(apr_file_t **wakeup_pipe)
+{
+    return APR_ENOTIMPL;
+}
+
+#endif /* !WIN32 */
+
+#else  /* APR_FILES_AS_SOCKETS */
+
+apr_status_t create_wakeup_pipe(apr_pool_t *pool, apr_pollfd_t *pfd,
+                                apr_file_t **wakeup_pipe)
+{
+    apr_status_t rv;
+
+    if ((rv = apr_file_pipe_create(&wakeup_pipe[0], &wakeup_pipe[1],
+                                   pool)) != APR_SUCCESS)
+        return rv;
+
+    pfd->p = pool;
+    pfd->reqevents = APR_POLLIN;
+    pfd->desc_type = APR_POLL_FILE;
+    pfd->desc.f = wakeup_pipe[0];
+
+    {
+        int flags;
+
+        if ((flags = fcntl(wakeup_pipe[0]->filedes, F_GETFD)) == -1)
+            return errno;
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(wakeup_pipe[0]->filedes, F_SETFD, flags) == -1)
+            return errno;
+    }
+    {
+        int flags;
+
+        if ((flags = fcntl(wakeup_pipe[1]->filedes, F_GETFD)) == -1)
+            return errno;
+
+        flags |= FD_CLOEXEC;
+        if (fcntl(wakeup_pipe[1]->filedes, F_SETFD, flags) == -1)
+            return errno;
+    }
+
+    return APR_SUCCESS;
+}
+
+apr_status_t close_wakeup_pipe(apr_file_t **wakeup_pipe)
+{
+    apr_status_t rv0 = APR_SUCCESS;
+    apr_status_t rv1 = APR_SUCCESS;
+
+    /* Close both sides of the wakeup pipe */
+    if (wakeup_pipe[0]) {
+        rv0 = apr_file_close(wakeup_pipe[0]);
+        wakeup_pipe[0] = NULL;
+    }
+    if (wakeup_pipe[1]) {
+        rv1 = apr_file_close(wakeup_pipe[1]);
+        wakeup_pipe[1] = NULL;
+    }
+    return rv0 ? rv0 : rv1;
+}
+
+#endif /* APR_FILES_AS_SOCKETS */
+
+/* Read and discard whatever is in the wakeup pipe.
+ */
+void drain_wakeup_pipe(apr_file_t **wakeup_pipe)
+{
+    char rb[512];
+    apr_size_t nr = sizeof(rb);
+
+    while (apr_file_read(wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
+        /* Although we write just one byte to the other end of the pipe
+         * during wakeup, multiple threads could call the wakeup.
+         * So simply drain out from the input side of the pipe all
+         * the data.
+         */
+        if (nr != sizeof(rb))
+            break;
+    }
+}

Modified: apr/apr/trunk/test/testpoll.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/test/testpoll.c?rev=899905&r1=899904&r2=899905&view=diff
==============================================================================
--- apr/apr/trunk/test/testpoll.c (original)
+++ apr/apr/trunk/test/testpoll.c Sat Jan 16 08:53:33 2010
@@ -586,9 +586,9 @@
     int count;
 } pollcb_baton_t;
 
-static apr_status_t trigger_pollcb_cb(void* baton, apr_pollfd_t *descriptor)
+static apr_status_t trigger_pollcb_cb(void *baton, apr_pollfd_t *descriptor)
 {
-    pollcb_baton_t* pcb = (pollcb_baton_t*) baton;
+    pollcb_baton_t *pcb = (pollcb_baton_t *) baton;
     ABTS_PTR_EQUAL(pcb->tc, s[0], descriptor->desc.s);
     ABTS_PTR_EQUAL(pcb->tc, s[0], descriptor->client_data);
     pcb->count++;
@@ -769,6 +769,56 @@
     }
 }
 
+static void pollset_wakeup(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_pollset_t *pollset;
+    apr_int32_t num;
+    const apr_pollfd_t *descriptors;
+
+    rv = apr_pollset_create(&pollset, 1, p, APR_POLLSET_WAKEABLE);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "apr_pollset_wakeup() not supported");
+        return;
+    }
+
+    rv = apr_pollset_wakeup(pollset);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_pollset_poll(pollset, -1, &num, &descriptors);
+    ABTS_INT_EQUAL(tc, APR_EINTR, rv);
+}
+
+/* Should never be invoked */
+static apr_status_t wakeup_pollcb_cb(void *baton, apr_pollfd_t *descriptor)
+{
+    abts_case *tc = (abts_case *) baton;
+
+    ABTS_FAIL(tc, "pollcb callback invoked on apr_pollcb_wakeup()");
+    return APR_SUCCESS;
+}
+
+static void pollcb_wakeup(abts_case *tc, void *data)
+{
+    apr_status_t rv;
+    apr_pollcb_t *pcb;
+
+    rv = apr_pollcb_create(&pcb, 1, p, APR_POLLSET_WAKEABLE);
+    if (rv == APR_ENOTIMPL) {
+        ABTS_NOT_IMPL(tc, "pollcb interface not supported");
+        return;
+    }
+    else {
+        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+    }
+
+    rv = apr_pollcb_wakeup(pcb);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
+
+    rv = apr_pollcb_poll(pcb, -1, wakeup_pollcb_cb, tc);
+    ABTS_INT_EQUAL(tc, APR_EINTR, rv);
+}
+
 abts_suite *testpoll(abts_suite *suite)
 {
     suite = ADD_SUITE(suite)
@@ -808,6 +858,9 @@
     abts_run_test(suite, close_all_sockets, NULL);
     abts_run_test(suite, pollset_default, NULL);
     abts_run_test(suite, pollcb_default, NULL);
+
+    abts_run_test(suite, pollset_wakeup, NULL);
+    abts_run_test(suite, pollcb_wakeup, NULL);
     return suite;
 }
 



Mime
View raw message