int main (int argc, char *const *argv) { int i; time_t start_t, end_t; int result = 0; MHD_THRD_RTRN_TYPE_ (MHD_THRD_CALL_SPEC_ *test_func)(void* data); #ifdef MHD_WINSOCK_SOCKETS WORD ver_req; WSADATA wsa_data; int err; #endif /* MHD_WINSOCK_SOCKETS */ bool test_poll; test_poll = has_in_name(argv[0], "_poll"); if (!test_poll) test_func = &select_thread; else { #ifndef HAVE_POLL return 77; #else /* ! HAVE_POLL */ test_func = &poll_thread; #endif /* ! HAVE_POLL */ } #ifdef MHD_WINSOCK_SOCKETS ver_req = MAKEWORD(2, 2); err = WSAStartup(ver_req, &wsa_data); if (err != 0 || MAKEWORD(2, 2) != wsa_data.wVersion) { printf("WSAStartup() failed\n"); WSACleanup(); return 99; } #endif /* MHD_WINSOCK_SOCKETS */ /* try several times to ensure that accidental incoming connection * didn't interfere with test results */ for (i = 0; i < 5 && result == 0; i++) { MHD_thread_handle_ sel_thrd; /* fprintf(stdout, "Creating, binding and listening socket...\n"); */ MHD_socket listen_socket = start_socket_listen (AF_INET); if (MHD_INVALID_SOCKET == listen_socket) return 99; check_err = !0; /* fprintf (stdout, "Starting select() thread...\n"); */ #if defined(MHD_USE_POSIX_THREADS) if (0 != pthread_create (&sel_thrd, NULL, test_func, &listen_socket)) { MHD_socket_close_chk_ (listen_socket); fprintf (stderr, "Can't start thread\n"); return 99; } #elif defined(MHD_USE_W32_THREADS) sel_thrd = (HANDLE)_beginthreadex (NULL, 0, test_func, &listen_socket, 0, NULL); if (0 == (sel_thrd)) { MHD_socket_close_chk_ (listen_socket); fprintf (stderr, "Can't start select() thread\n"); return 99; } #else #error No threading lib available #endif /* fprintf (stdout, "Waiting...\n"); */ local_sleep(1); /* make sure that select() is started */ /* fprintf (stdout, "Shutting down socket...\n"); */ start_t = time (NULL); shutdown (listen_socket, SHUT_RDWR); /* fprintf (stdout, "Waiting for thread to finish...\n"); */ if (!MHD_join_thread_(sel_thrd)) { MHD_socket_close_chk_(listen_socket); fprintf (stderr, "Can't join select() thread\n"); return 99; } if (check_err) { MHD_socket_close_chk_(listen_socket); fprintf (stderr, "Error in waiting thread\n"); return 99; } end_t = time (NULL); /* fprintf (stdout, "Thread finished.\n"); */ MHD_socket_close_chk_(listen_socket); if (start_t == (time_t)-1 || end_t == (time_t)-1) { MHD_socket_close_chk_(listen_socket); fprintf (stderr, "Can't get current time\n"); return 99; } if (end_t - start_t > 3) result++; } #ifdef MHD_WINSOCK_SOCKETS WSACleanup(); #endif /* MHD_WINSOCK_SOCKETS */ return result; }
/** * Shutdown and destroy an HTTP daemon. * * @param daemon daemon to stop * @ingroup event */ void MHD_daemon_destroy (struct MHD_Daemon *daemon) { MHD_socket fd; daemon->shutdown = true; if (daemon->was_quiesced) fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */ else fd = daemon->listen_socket; /* FIXME: convert from here to microhttpd2-style API! */ if (NULL != daemon->worker_pool) { /* Master daemon with worker pool. */ stop_workers (daemon); } else { mhd_assert (0 == daemon->worker_pool_size); /* Worker daemon or single-thread daemon. */ if (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) { /* Worker daemon or single daemon with internal thread(s). */ /* Separate thread(s) is used for polling sockets. */ if (MHD_ITC_IS_VALID_(daemon->itc)) { if (! MHD_itc_activate_ (daemon->itc, "e")) MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel")); } else { #ifdef HAVE_LISTEN_SHUTDOWN if (MHD_INVALID_SOCKET != fd) { if (NULL == daemon->master) (void) shutdown (fd, SHUT_RDWR); } else #endif /* HAVE_LISTEN_SHUTDOWN */ mhd_assert (false); /* Should never happen */ } if (! MHD_join_thread_ (daemon->pid.handle)) { MHD_PANIC (_("Failed to join a thread\n")); } /* close_all_connections() was called in daemon thread. */ } else { /* No internal threads are used for polling sockets (external event loop) */ MHD_daemon_close_all_connections_ (daemon); } if (MHD_ITC_IS_VALID_ (daemon->itc)) MHD_itc_destroy_chk_ (daemon->itc); #ifdef EPOLL_SUPPORT if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) && (-1 != daemon->epoll_fd) ) MHD_socket_close_chk_ (daemon->epoll_fd); #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) && (-1 != daemon->epoll_upgrade_fd) ) MHD_socket_close_chk_ (daemon->epoll_upgrade_fd); #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ #endif /* EPOLL_SUPPORT */ MHD_mutex_destroy_chk_ (&daemon->cleanup_connection_mutex); } if (NULL != daemon->master) return; /* Cleanup that should be done only one time in master/single daemon. * Do not perform this cleanup in worker daemons. */ if (MHD_INVALID_SOCKET != fd) MHD_socket_close_chk_ (fd); /* TLS clean up */ #ifdef HTTPS_SUPPORT if (NULL != daemon->tls_api) { #if FIXME_TLS_API if (daemon->have_dhparams) { gnutls_dh_params_deinit (daemon->https_mem_dhparams); daemon->have_dhparams = false; } gnutls_priority_deinit (daemon->priority_cache); if (daemon->x509_cred) gnutls_certificate_free_credentials (daemon->x509_cred); #endif } #endif /* HTTPS_SUPPORT */ #ifdef DAUTH_SUPPORT free (daemon->nnc); MHD_mutex_destroy_chk_ (&daemon->nnc_lock); #endif MHD_mutex_destroy_chk_ (&daemon->per_ip_connection_mutex); free (daemon); }