void *socket_listen_main_single_threaded(void *ptr) { struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; web_server_mode = WEB_SERVER_MODE_SINGLE_THREADED; info("Single-threaded WEB SERVER thread created with task id %d", gettid()); struct web_client *w; int retval; if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) error("Cannot set pthread cancel type to DEFERRED."); if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("Cannot set pthread cancel state to ENABLE."); if(!api_sockets.opened) fatal("LISTENER: no listen sockets available."); size_t i; for(i = 0; i < FD_SETSIZE ; i++) single_threaded_clients[i] = NULL; fd_set ifds, ofds, efds, rifds, rofds, refds; FD_ZERO (&ifds); FD_ZERO (&ofds); FD_ZERO (&efds); int fdmax = 0; for(i = 0; i < api_sockets.opened ; i++) { if (api_sockets.fds[i] < 0 || api_sockets.fds[i] >= FD_SETSIZE) fatal("LISTENER: Listen socket %d is not ready, or invalid.", api_sockets.fds[i]); info("Listening on '%s'", (api_sockets.fds_names[i])?api_sockets.fds_names[i]:"UNKNOWN"); FD_SET(api_sockets.fds[i], &ifds); FD_SET(api_sockets.fds[i], &efds); if(fdmax < api_sockets.fds[i]) fdmax = api_sockets.fds[i]; } for(;;) { debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server waiting (fdmax = %d)...", fdmax); struct timeval tv = { .tv_sec = 1, .tv_usec = 0 }; rifds = ifds; rofds = ofds; refds = efds; retval = select(fdmax+1, &rifds, &rofds, &refds, &tv); if(unlikely(retval == -1)) { error("LISTENER: select() failed."); continue; } else if(likely(retval)) { debug(D_WEB_CLIENT_ACCESS, "LISTENER: got something."); for(i = 0; i < api_sockets.opened ; i++) { if (FD_ISSET(api_sockets.fds[i], &rifds)) { debug(D_WEB_CLIENT_ACCESS, "LISTENER: new connection."); w = web_client_create(api_sockets.fds[i]); if(api_sockets.fds_families[i] == AF_UNIX) web_client_set_unix(w); else web_client_set_tcp(w); if (single_threaded_link_client(w, &ifds, &ofds, &ifds, &fdmax) != 0) { web_client_free(w); } } } for(i = 0 ; i <= (size_t)fdmax ; i++) { if(likely(!FD_ISSET(i, &rifds) && !FD_ISSET(i, &rofds) && !FD_ISSET(i, &refds))) continue; w = single_threaded_clients[i]; if(unlikely(!w)) continue; if(unlikely(single_threaded_unlink_client(w, &ifds, &ofds, &efds) != 0)) { web_client_free(w); continue; } if (unlikely(FD_ISSET(w->ifd, &refds) || FD_ISSET(w->ofd, &refds))) { web_client_free(w); continue; } if (unlikely(web_client_has_wait_receive(w) && FD_ISSET(w->ifd, &rifds))) { if (unlikely(web_client_receive(w) < 0)) { web_client_free(w); continue; } if (w->mode != WEB_CLIENT_MODE_FILECOPY) { debug(D_WEB_CLIENT, "%llu: Processing received data.", w->id); web_client_process_request(w); } } if (unlikely(web_client_has_wait_send(w) && FD_ISSET(w->ofd, &rofds))) { if (unlikely(web_client_send(w) < 0)) { debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id); web_client_free(w); continue; } } if(unlikely(single_threaded_link_client(w, &ifds, &ofds, &efds, &fdmax) != 0)) { web_client_free(w); } } } else { debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server timeout."); #ifdef NETDATA_INTERNAL_CHECKS log_allocations(); #endif } } debug(D_WEB_CLIENT, "LISTENER: exit!"); listen_sockets_close(&api_sockets); static_thread->enabled = 0; pthread_exit(NULL); return NULL; }
void *socket_listen_main_single_threaded(void *ptr) { netdata_thread_cleanup_push(socket_listen_main_single_threaded_cleanup, ptr); web_server_mode = WEB_SERVER_MODE_SINGLE_THREADED; web_server_is_multithreaded = 0; struct web_client *w; if(!api_sockets.opened) fatal("LISTENER: no listen sockets available."); size_t i; for(i = 0; i < (size_t)FD_SETSIZE ; i++) single_threaded_clients[i] = NULL; fd_set ifds, ofds, efds, rifds, rofds, refds; FD_ZERO (&ifds); FD_ZERO (&ofds); FD_ZERO (&efds); int fdmax = 0; for(i = 0; i < api_sockets.opened ; i++) { if (api_sockets.fds[i] < 0 || api_sockets.fds[i] >= (int)FD_SETSIZE) fatal("LISTENER: Listen socket %d is not ready, or invalid.", api_sockets.fds[i]); info("Listening on '%s'", (api_sockets.fds_names[i])?api_sockets.fds_names[i]:"UNKNOWN"); FD_SET(api_sockets.fds[i], &ifds); FD_SET(api_sockets.fds[i], &efds); if(fdmax < api_sockets.fds[i]) fdmax = api_sockets.fds[i]; } while(!netdata_exit) { debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server waiting (fdmax = %d)...", fdmax); struct timeval tv = { .tv_sec = 1, .tv_usec = 0 }; rifds = ifds; rofds = ofds; refds = efds; int retval = select(fdmax+1, &rifds, &rofds, &refds, &tv); if(unlikely(retval == -1)) { error("LISTENER: select() failed."); continue; } else if(likely(retval)) { debug(D_WEB_CLIENT_ACCESS, "LISTENER: got something."); for(i = 0; i < api_sockets.opened ; i++) { if (FD_ISSET(api_sockets.fds[i], &rifds)) { debug(D_WEB_CLIENT_ACCESS, "LISTENER: new connection."); w = web_client_create_on_listenfd(api_sockets.fds[i]); if(unlikely(!w)) continue; if(api_sockets.fds_families[i] == AF_UNIX) web_client_set_unix(w); else web_client_set_tcp(w); if (single_threaded_link_client(w, &ifds, &ofds, &ifds, &fdmax) != 0) { web_client_release(w); } } } for(i = 0 ; i <= (size_t)fdmax ; i++) { if(likely(!FD_ISSET(i, &rifds) && !FD_ISSET(i, &rofds) && !FD_ISSET(i, &refds))) continue; w = single_threaded_clients[i]; if(unlikely(!w)) { // error("no client on slot %zu", i); continue; } if(unlikely(single_threaded_unlink_client(w, &ifds, &ofds, &efds) != 0)) { // error("failed to unlink client %zu", i); web_client_release(w); continue; } if (unlikely(FD_ISSET(w->ifd, &refds) || FD_ISSET(w->ofd, &refds))) { // error("no input on client %zu", i); web_client_release(w); continue; } if (unlikely(web_client_has_wait_receive(w) && FD_ISSET(w->ifd, &rifds))) { if (unlikely(web_client_receive(w) < 0)) { // error("cannot read from client %zu", i); web_client_release(w); continue; } if (w->mode != WEB_CLIENT_MODE_FILECOPY) { debug(D_WEB_CLIENT, "%llu: Processing received data.", w->id); web_client_process_request(w); } } if (unlikely(web_client_has_wait_send(w) && FD_ISSET(w->ofd, &rofds))) { if (unlikely(web_client_send(w) < 0)) { // error("cannot send data to client %zu", i); debug(D_WEB_CLIENT, "%llu: Cannot send data to client. Closing client.", w->id); web_client_release(w); continue; } } if(unlikely(single_threaded_link_client(w, &ifds, &ofds, &efds, &fdmax) != 0)) { // error("failed to link client %zu", i); web_client_release(w); } } } else { debug(D_WEB_CLIENT_ACCESS, "LISTENER: single threaded web server timeout."); } } netdata_thread_cleanup_pop(1); return NULL; }