trac 18 deal with service connection timing out
authorAndy Green <andy.green@linaro.org>
Wed, 20 Feb 2013 11:11:31 +0000 (19:11 +0800)
committerAndy Green <andy.green@linaro.org>
Wed, 20 Feb 2013 11:11:31 +0000 (19:11 +0800)
While looking at http://libwebsockets.org/trac/ticket/18
noticed the flow for timeout in service_fd will do bad things
if the fd we came to service has timed out.  It gets freed and
then "serviced'.

Reported-by: Joakim Soderberg <joakim.soderberg@gmail.com>
Signed-off-by: Andy Green <andy.green@linaro.org>
lib/libwebsockets.c
lib/private-libwebsockets.h

index 0291acb..8756de7 100644 (file)
@@ -760,7 +760,7 @@ notify_action:
 
 
 
-void
+int
 libwebsocket_service_timeout_check(struct libwebsocket_context *context,
                                     struct libwebsocket *wsi, unsigned int sec)
 {
@@ -780,7 +780,7 @@ libwebsocket_service_timeout_check(struct libwebsocket_context *context,
 
 #endif
        if (!wsi->pending_timeout)
-               return;
+               return 0;
 
        /*
         * if we went beyond the allowed time, kill the
@@ -791,7 +791,10 @@ libwebsocket_service_timeout_check(struct libwebsocket_context *context,
                lwsl_info("TIMEDOUT WAITING\n");
                libwebsocket_close_and_free_session(context,
                                wsi, LWS_CLOSE_STATUS_NOSTATUS);
+               return 1;
        }
+
+       return 0;
 }
 
 /**
@@ -817,6 +820,8 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
        int m;
        int listen_socket_fds_index = 0;
        struct timeval tv;
+       int timed_out = 0;
+       int our_fd = 0;
 
 #ifndef LWS_NO_EXTENSIONS
        int more = 1;
@@ -847,16 +852,28 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
 
                /* global timeout check once per second */
 
+               if (pollfd)
+                       our_fd = pollfd->fd;
+
                for (n = 0; n < context->fds_count; n++) {
-                       struct libwebsocket *new_wsi =
-                                       context->lws_lookup[context->fds[n].fd];
-                       if (!new_wsi)
+                       m = context->fds[n].fd;
+                       wsi = context->lws_lookup[m];
+                       if (!wsi)
                                continue;
-                       libwebsocket_service_timeout_check(context,
-                               new_wsi, tv.tv_sec);
+
+                       if (libwebsocket_service_timeout_check(context, wsi,
+                                                                    tv.tv_sec))
+                               /* he did time out... */
+                               if (m == our_fd)
+                                       /* it was the guy we came to service! */
+                                       timed_out = 1;
                }
        }
 
+       /* the socket we came to service timed out, nothing to do */
+       if (timed_out)
+               return 0;
+
        /* just here for timeout management? */
 
        if (pollfd == NULL)
index 3bde491..f8e9fc8 100644 (file)
@@ -444,7 +444,7 @@ LWS_EXTERN int
 lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len);
 
 
-LWS_EXTERN void
+LWS_EXTERN int
 libwebsocket_service_timeout_check(struct libwebsocket_context *context,
                                    struct libwebsocket *wsi, unsigned int sec);