aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-02-14 18:39:10 +0100
committerChristian Grothoff <christian@grothoff.org>2017-02-14 18:39:10 +0100
commit8145670329c735a028146e6d5232b34a10adc256 (patch)
treecdfcd5e6ca3ee90dc181d8dbae7d8df31b051f69
parentba9f1fc809a2de1444e07104f234c89acac55c0d (diff)
downloadlibmicrohttpd-8145670329c735a028146e6d5232b34a10adc256.tar.gz
libmicrohttpd-8145670329c735a028146e6d5232b34a10adc256.zip
found another race, just with partial work-around for now; also init errno in all cases
-rw-r--r--src/microhttpd/daemon.c49
-rw-r--r--src/testcurl/test_get_response_cleanup.c10
-rw-r--r--src/testcurl/test_quiesce_stream.c4
3 files changed, 40 insertions, 23 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index bc26b53f..a8997d87 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -775,6 +775,7 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon,
775 struct MHD_Connection *pos; 775 struct MHD_Connection *pos;
776 struct MHD_Connection *posn; 776 struct MHD_Connection *posn;
777 int result = MHD_YES; 777 int result = MHD_YES;
778 MHD_socket ls;
778 779
779 if ( (NULL == daemon) || 780 if ( (NULL == daemon) ||
780 (NULL == read_fd_set) || 781 (NULL == read_fd_set) ||
@@ -795,8 +796,9 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon,
795 fd_setsize) ? MHD_YES : MHD_NO; 796 fd_setsize) ? MHD_YES : MHD_NO;
796 } 797 }
797#endif 798#endif
798 if ( (MHD_INVALID_SOCKET != daemon->socket_fd) && 799 ls = daemon->socket_fd;
799 (! MHD_add_to_fd_set_ (daemon->socket_fd, 800 if ( (MHD_INVALID_SOCKET != ls) &&
801 (! MHD_add_to_fd_set_ (ls,
800 read_fd_set, 802 read_fd_set,
801 max_fd, 803 max_fd,
802 fd_setsize)) ) 804 fd_setsize)) )
@@ -2222,6 +2224,7 @@ internal_add_connection (struct MHD_Daemon *daemon,
2222 gnutls_certificate_server_set_request (connection->tls_session, 2224 gnutls_certificate_server_set_request (connection->tls_session,
2223 GNUTLS_CERT_REQUEST); 2225 GNUTLS_CERT_REQUEST);
2224#else /* ! HTTPS_SUPPORT */ 2226#else /* ! HTTPS_SUPPORT */
2227 eno = EINVAL;
2225 goto cleanup; 2228 goto cleanup;
2226#endif /* ! HTTPS_SUPPORT */ 2229#endif /* ! HTTPS_SUPPORT */
2227 } 2230 }
@@ -2688,7 +2691,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
2688 /* This could be a common occurance with multiple worker threads */ 2691 /* This could be a common occurance with multiple worker threads */
2689 if ( (MHD_SCKT_ERR_IS_ (err, 2692 if ( (MHD_SCKT_ERR_IS_ (err,
2690 MHD_SCKT_EINVAL_)) && 2693 MHD_SCKT_EINVAL_)) &&
2691 (MHD_INVALID_SOCKET == daemon->socket_fd) ) 2694 (MHD_INVALID_SOCKET == fd) )
2692 return MHD_NO; /* can happen during shutdown */ 2695 return MHD_NO; /* can happen during shutdown */
2693 if (MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)) 2696 if (MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err))
2694 return MHD_NO; /* do not print error if client just disconnected early */ 2697 return MHD_NO; /* do not print error if client just disconnected early */
@@ -3105,6 +3108,7 @@ MHD_select (struct MHD_Daemon *daemon,
3105 struct timeval *tv; 3108 struct timeval *tv;
3106 MHD_UNSIGNED_LONG_LONG ltimeout; 3109 MHD_UNSIGNED_LONG_LONG ltimeout;
3107 int err_state; 3110 int err_state;
3111 MHD_socket ls;
3108 3112
3109 timeout.tv_sec = 0; 3113 timeout.tv_sec = 0;
3110 timeout.tv_usec = 0; 3114 timeout.tv_usec = 0;
@@ -3140,8 +3144,8 @@ MHD_select (struct MHD_Daemon *daemon,
3140 else 3144 else
3141 { 3145 {
3142 /* accept only, have one thread per connection */ 3146 /* accept only, have one thread per connection */
3143 if ( (MHD_INVALID_SOCKET != daemon->socket_fd) && 3147 if ( (MHD_INVALID_SOCKET != (ls = daemon->socket_fd)) &&
3144 (! MHD_add_to_fd_set_ (daemon->socket_fd, 3148 (! MHD_add_to_fd_set_ (ls,
3145 &rs, 3149 &rs,
3146 &maxsock, 3150 &maxsock,
3147 FD_SETSIZE)) ) 3151 FD_SETSIZE)) )
@@ -3163,9 +3167,9 @@ MHD_select (struct MHD_Daemon *daemon,
3163 /* fdset limit reached, new connections 3167 /* fdset limit reached, new connections
3164 cannot be handled. Remove listen socket FD 3168 cannot be handled. Remove listen socket FD
3165 from fdset and retry to add ITC FD. */ 3169 from fdset and retry to add ITC FD. */
3166 if (MHD_INVALID_SOCKET != daemon->socket_fd) 3170 if (MHD_INVALID_SOCKET != (ls = daemon->socket_fd))
3167 { 3171 {
3168 FD_CLR (daemon->socket_fd, 3172 FD_CLR (ls,
3169 &rs); 3173 &rs);
3170 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_(daemon->itc), 3174 if (! MHD_add_to_fd_set_ (MHD_itc_r_fd_(daemon->itc),
3171 &rs, 3175 &rs,
@@ -3189,13 +3193,13 @@ MHD_select (struct MHD_Daemon *daemon,
3189 the shutdown OR the termination of an existing connection; so 3193 the shutdown OR the termination of an existing connection; so
3190 only do this optimization if we have a signaling ITC in 3194 only do this optimization if we have a signaling ITC in
3191 place. */ 3195 place. */
3192 if ( (MHD_INVALID_SOCKET != daemon->socket_fd) && 3196 if ( (MHD_INVALID_SOCKET != (ls = daemon->socket_fd)) &&
3193 (MHD_ITC_IS_VALID_(daemon->itc)) && 3197 (MHD_ITC_IS_VALID_(daemon->itc)) &&
3194 (0 != (daemon->options & MHD_USE_ITC)) && 3198 (0 != (daemon->options & MHD_USE_ITC)) &&
3195 ( (daemon->connections == daemon->connection_limit) || 3199 ( (daemon->connections == daemon->connection_limit) ||
3196 (daemon->at_limit) ) ) 3200 (daemon->at_limit) ) )
3197 { 3201 {
3198 FD_CLR (daemon->socket_fd, 3202 FD_CLR (ls,
3199 &rs); 3203 &rs);
3200 } 3204 }
3201 tv = NULL; 3205 tv = NULL;
@@ -3287,6 +3291,7 @@ MHD_poll_all (struct MHD_Daemon *daemon,
3287 int poll_listen; 3291 int poll_listen;
3288 int poll_itc_idx; 3292 int poll_itc_idx;
3289 struct pollfd *p; 3293 struct pollfd *p;
3294 MHD_socket ls;
3290 3295
3291 p = MHD_calloc_ ((2 + num_connections), sizeof (struct pollfd)); 3296 p = MHD_calloc_ ((2 + num_connections), sizeof (struct pollfd));
3292 if (NULL == p) 3297 if (NULL == p)
@@ -3300,12 +3305,12 @@ MHD_poll_all (struct MHD_Daemon *daemon,
3300 } 3305 }
3301 poll_server = 0; 3306 poll_server = 0;
3302 poll_listen = -1; 3307 poll_listen = -1;
3303 if ( (MHD_INVALID_SOCKET != daemon->socket_fd) && 3308 if ( (MHD_INVALID_SOCKET != (ls = daemon->socket_fd)) &&
3304 (daemon->connections < daemon->connection_limit) && 3309 (daemon->connections < daemon->connection_limit) &&
3305 (! daemon->at_limit) ) 3310 (! daemon->at_limit) )
3306 { 3311 {
3307 /* only listen if we are not at the connection limit */ 3312 /* only listen if we are not at the connection limit */
3308 p[poll_server].fd = daemon->socket_fd; 3313 p[poll_server].fd = ls;
3309 p[poll_server].events = POLLIN; 3314 p[poll_server].events = POLLIN;
3310 p[poll_server].revents = 0; 3315 p[poll_server].revents = 0;
3311 poll_listen = (int) poll_server; 3316 poll_listen = (int) poll_server;
@@ -3503,6 +3508,7 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
3503 unsigned int poll_count; 3508 unsigned int poll_count;
3504 int poll_listen; 3509 int poll_listen;
3505 int poll_itc_idx; 3510 int poll_itc_idx;
3511 MHD_socket ls;
3506 3512
3507 memset (&p, 3513 memset (&p,
3508 0, 3514 0,
@@ -3510,9 +3516,9 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
3510 poll_count = 0; 3516 poll_count = 0;
3511 poll_listen = -1; 3517 poll_listen = -1;
3512 poll_itc_idx = -1; 3518 poll_itc_idx = -1;
3513 if (MHD_INVALID_SOCKET != daemon->socket_fd) 3519 if (MHD_INVALID_SOCKET != (ls = daemon->socket_fd))
3514 { 3520 {
3515 p[poll_count].fd = daemon->socket_fd; 3521 p[poll_count].fd = ls;
3516 p[poll_count].events = POLLIN; 3522 p[poll_count].events = POLLIN;
3517 p[poll_count].revents = 0; 3523 p[poll_count].revents = 0;
3518 poll_listen = poll_count; 3524 poll_listen = poll_count;
@@ -3701,6 +3707,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
3701 MHD_UNSIGNED_LONG_LONG timeout_ll; 3707 MHD_UNSIGNED_LONG_LONG timeout_ll;
3702 int num_events; 3708 int num_events;
3703 unsigned int i; 3709 unsigned int i;
3710 MHD_socket ls;
3704#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3711#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3705 int run_upgraded = MHD_NO; 3712 int run_upgraded = MHD_NO;
3706#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 3713#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
@@ -3709,7 +3716,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
3709 return MHD_NO; /* we're down! */ 3716 return MHD_NO; /* we're down! */
3710 if (daemon->shutdown) 3717 if (daemon->shutdown)
3711 return MHD_NO; 3718 return MHD_NO;
3712 if ( (MHD_INVALID_SOCKET != daemon->socket_fd) && 3719 if ( (MHD_INVALID_SOCKET != (ls = daemon->socket_fd)) &&
3713 (daemon->connections < daemon->connection_limit) && 3720 (daemon->connections < daemon->connection_limit) &&
3714 (MHD_NO == daemon->listen_socket_in_epoll) && 3721 (MHD_NO == daemon->listen_socket_in_epoll) &&
3715 (! daemon->at_limit) ) 3722 (! daemon->at_limit) )
@@ -3718,7 +3725,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
3718 event.data.ptr = daemon; 3725 event.data.ptr = daemon;
3719 if (0 != epoll_ctl (daemon->epoll_fd, 3726 if (0 != epoll_ctl (daemon->epoll_fd,
3720 EPOLL_CTL_ADD, 3727 EPOLL_CTL_ADD,
3721 daemon->socket_fd, 3728 ls,
3722 &event)) 3729 &event))
3723 { 3730 {
3724#ifdef HAVE_MESSAGES 3731#ifdef HAVE_MESSAGES
@@ -3759,7 +3766,7 @@ MHD_epoll (struct MHD_Daemon *daemon,
3759 for event loop for now */ 3766 for event loop for now */
3760 if (0 != epoll_ctl (daemon->epoll_fd, 3767 if (0 != epoll_ctl (daemon->epoll_fd,
3761 EPOLL_CTL_DEL, 3768 EPOLL_CTL_DEL,
3762 daemon->socket_fd, 3769 ls,
3763 NULL)) 3770 NULL))
3764 MHD_PANIC (_("Failed to remove listen FD from epoll set\n")); 3771 MHD_PANIC (_("Failed to remove listen FD from epoll set\n"));
3765 daemon->listen_socket_in_epoll = MHD_NO; 3772 daemon->listen_socket_in_epoll = MHD_NO;
@@ -4141,7 +4148,7 @@ MHD_start_daemon (unsigned int flags,
4141 * returned socket; however, if MHD is run using threads (anything but 4148 * returned socket; however, if MHD is run using threads (anything but
4142 * external select mode), socket will be removed from existing threads 4149 * external select mode), socket will be removed from existing threads
4143 * with some delay and it must not be closed while it's in use. To make 4150 * with some delay and it must not be closed while it's in use. To make
4144 * sure that socket is not used anymore, call #MHD_stop_daemon. 4151 * sure that the socket is not used anymore, call #MHD_stop_daemon.
4145 * 4152 *
4146 * Note that some thread modes require the caller to have passed 4153 * Note that some thread modes require the caller to have passed
4147 * #MHD_USE_ITC when using this API. If this daemon is 4154 * #MHD_USE_ITC when using this API. If this daemon is
@@ -4196,6 +4203,9 @@ MHD_quiesce_daemon (struct MHD_Daemon *daemon)
4196 MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel")); 4203 MHD_PANIC (_("Failed to signal quiesce via inter-thread communication channel"));
4197 } 4204 }
4198 } 4205 }
4206 /* FIXME: This creates a race with the rest of the code.
4207 We may be adding the FD to the epoll-set concurrently
4208 in another thread! So we DO need to lock (yuck yuck). */
4199 daemon->socket_fd = MHD_INVALID_SOCKET; 4209 daemon->socket_fd = MHD_INVALID_SOCKET;
4200#ifdef EPOLL_SUPPORT 4210#ifdef EPOLL_SUPPORT
4201 if ( (0 != (daemon->options & MHD_USE_EPOLL)) && 4211 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
@@ -4698,6 +4708,7 @@ static int
4698setup_epoll_to_listen (struct MHD_Daemon *daemon) 4708setup_epoll_to_listen (struct MHD_Daemon *daemon)
4699{ 4709{
4700 struct epoll_event event; 4710 struct epoll_event event;
4711 MHD_socket ls;
4701 4712
4702 daemon->epoll_fd = setup_epoll_fd (daemon); 4713 daemon->epoll_fd = setup_epoll_fd (daemon);
4703 if (-1 == daemon->epoll_fd) 4714 if (-1 == daemon->epoll_fd)
@@ -4710,13 +4721,13 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon)
4710 return MHD_NO; 4721 return MHD_NO;
4711 } 4722 }
4712#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 4723#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
4713 if (MHD_INVALID_SOCKET == daemon->socket_fd) 4724 if (MHD_INVALID_SOCKET == (ls = daemon->socket_fd))
4714 return MHD_YES; /* non-listening daemon */ 4725 return MHD_YES; /* non-listening daemon */
4715 event.events = EPOLLIN; 4726 event.events = EPOLLIN;
4716 event.data.ptr = daemon; 4727 event.data.ptr = daemon;
4717 if (0 != epoll_ctl (daemon->epoll_fd, 4728 if (0 != epoll_ctl (daemon->epoll_fd,
4718 EPOLL_CTL_ADD, 4729 EPOLL_CTL_ADD,
4719 daemon->socket_fd, 4730 ls,
4720 &event)) 4731 &event))
4721 { 4732 {
4722#ifdef HAVE_MESSAGES 4733#ifdef HAVE_MESSAGES
diff --git a/src/testcurl/test_get_response_cleanup.c b/src/testcurl/test_get_response_cleanup.c
index 26b2ecda..2833899c 100644
--- a/src/testcurl/test_get_response_cleanup.c
+++ b/src/testcurl/test_get_response_cleanup.c
@@ -77,6 +77,7 @@ fork_curl (const char *url)
77 _exit (-1); 77 _exit (-1);
78} 78}
79 79
80
80static void 81static void
81kill_curl (pid_t pid) 82kill_curl (pid_t pid)
82{ 83{
@@ -97,6 +98,7 @@ push_callback (void *cls, uint64_t pos, char *buf, size_t max)
97 return 1; 98 return 1;
98} 99}
99 100
101
100static void 102static void
101push_free_callback (void *cls) 103push_free_callback (void *cls)
102{ 104{
@@ -165,19 +167,20 @@ testInternalGet ()
165 return 0; 167 return 0;
166} 168}
167 169
170
168static int 171static int
169testMultithreadedGet () 172testMultithreadedGet ()
170{ 173{
171 struct MHD_Daemon *d; 174 struct MHD_Daemon *d;
172 pid_t curl; 175 pid_t curl;
173 176
177 ok = 1;
174 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, 178 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
175 1081, NULL, NULL, &ahc_echo, "GET", 179 1081, NULL, NULL, &ahc_echo, "GET",
176 MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 2, 180 MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 2,
177 MHD_OPTION_END); 181 MHD_OPTION_END);
178 if (d == NULL) 182 if (d == NULL)
179 return 16; 183 return 16;
180 ok = 1;
181 //fprintf (stderr, "Forking cURL!\n"); 184 //fprintf (stderr, "Forking cURL!\n");
182 curl = fork_curl ("http://127.0.0.1:1081/"); 185 curl = fork_curl ("http://127.0.0.1:1081/");
183 sleep (1); 186 sleep (1);
@@ -201,18 +204,19 @@ testMultithreadedGet ()
201 return 0; 204 return 0;
202} 205}
203 206
207
204static int 208static int
205testMultithreadedPoolGet () 209testMultithreadedPoolGet ()
206{ 210{
207 struct MHD_Daemon *d; 211 struct MHD_Daemon *d;
208 pid_t curl; 212 pid_t curl;
209 213
214 ok = 1;
210 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, 215 d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
211 1081, NULL, NULL, &ahc_echo, "GET", 216 1081, NULL, NULL, &ahc_echo, "GET",
212 MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END); 217 MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, MHD_OPTION_END);
213 if (d == NULL) 218 if (d == NULL)
214 return 64; 219 return 64;
215 ok = 1;
216 curl = fork_curl ("http://127.0.0.1:1081/"); 220 curl = fork_curl ("http://127.0.0.1:1081/");
217 sleep (1); 221 sleep (1);
218 kill_curl (curl); 222 kill_curl (curl);
@@ -224,6 +228,7 @@ testMultithreadedPoolGet ()
224 return 0; 228 return 0;
225} 229}
226 230
231
227static int 232static int
228testExternalGet () 233testExternalGet ()
229{ 234{
@@ -236,6 +241,7 @@ testExternalGet ()
236 struct timeval tv; 241 struct timeval tv;
237 pid_t curl; 242 pid_t curl;
238 243
244 ok = 1;
239 d = MHD_start_daemon (MHD_USE_ERROR_LOG, 245 d = MHD_start_daemon (MHD_USE_ERROR_LOG,
240 1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END); 246 1082, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
241 if (d == NULL) 247 if (d == NULL)
diff --git a/src/testcurl/test_quiesce_stream.c b/src/testcurl/test_quiesce_stream.c
index 7885a048..38263e07 100644
--- a/src/testcurl/test_quiesce_stream.c
+++ b/src/testcurl/test_quiesce_stream.c
@@ -61,7 +61,7 @@ resume_connection (void *arg)
61{ 61{
62 struct MHD_Connection *connection = arg; 62 struct MHD_Connection *connection = arg;
63 63
64 fprintf (stderr, "Calling resume\n"); 64 /* fprintf (stderr, "Calling resume\n"); */
65 MHD_resume_connection (connection); 65 MHD_resume_connection (connection);
66 return NULL; 66 return NULL;
67} 67}
@@ -72,7 +72,7 @@ suspend_connection (struct MHD_Connection *connection)
72{ 72{
73 pthread_t thread_id; 73 pthread_t thread_id;
74 74
75 fprintf (stderr, "Calling suspend\n"); 75 /* fprintf (stderr, "Calling suspend\n"); */
76 MHD_suspend_connection (connection); 76 MHD_suspend_connection (connection);
77 int status = pthread_create (&thread_id, 77 int status = pthread_create (&thread_id,
78 NULL, 78 NULL,