trac 18 deal with service connection timing out

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>
This commit is contained in:
Andy Green 2013-02-20 19:11:31 +08:00
parent d75076eaea
commit 1c6e1422e6
2 changed files with 25 additions and 8 deletions

View file

@ -760,7 +760,7 @@ notify_action:
void int
libwebsocket_service_timeout_check(struct libwebsocket_context *context, libwebsocket_service_timeout_check(struct libwebsocket_context *context,
struct libwebsocket *wsi, unsigned int sec) struct libwebsocket *wsi, unsigned int sec)
{ {
@ -780,7 +780,7 @@ libwebsocket_service_timeout_check(struct libwebsocket_context *context,
#endif #endif
if (!wsi->pending_timeout) if (!wsi->pending_timeout)
return; return 0;
/* /*
* if we went beyond the allowed time, kill the * 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"); lwsl_info("TIMEDOUT WAITING\n");
libwebsocket_close_and_free_session(context, libwebsocket_close_and_free_session(context,
wsi, LWS_CLOSE_STATUS_NOSTATUS); wsi, LWS_CLOSE_STATUS_NOSTATUS);
return 1;
} }
return 0;
} }
/** /**
@ -817,6 +820,8 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
int m; int m;
int listen_socket_fds_index = 0; int listen_socket_fds_index = 0;
struct timeval tv; struct timeval tv;
int timed_out = 0;
int our_fd = 0;
#ifndef LWS_NO_EXTENSIONS #ifndef LWS_NO_EXTENSIONS
int more = 1; int more = 1;
@ -847,16 +852,28 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
/* global timeout check once per second */ /* global timeout check once per second */
if (pollfd)
our_fd = pollfd->fd;
for (n = 0; n < context->fds_count; n++) { for (n = 0; n < context->fds_count; n++) {
struct libwebsocket *new_wsi = m = context->fds[n].fd;
context->lws_lookup[context->fds[n].fd]; wsi = context->lws_lookup[m];
if (!new_wsi) if (!wsi)
continue; 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? */ /* just here for timeout management? */
if (pollfd == NULL) if (pollfd == NULL)

View file

@ -444,7 +444,7 @@ LWS_EXTERN int
lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len); 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, libwebsocket_service_timeout_check(struct libwebsocket_context *context,
struct libwebsocket *wsi, unsigned int sec); struct libwebsocket *wsi, unsigned int sec);