static int run_server(struct conf **confs, const char *conffile, int *rfds, int *sfds) { int i=0; int ret=-1; SSL_CTX *ctx=NULL; int found_normal_child=0; struct asfd *asfd=NULL; struct asfd *scfd=NULL; struct async *mainas=NULL; const char *port=get_string(confs[OPT_PORT]); const char *address=get_string(confs[OPT_ADDRESS]); const char *status_port=get_string(confs[OPT_STATUS_PORT]); const char *status_address=get_string(confs[OPT_STATUS_ADDRESS]); if(!(ctx=ssl_initialise_ctx(confs))) { logp("error initialising ssl ctx\n"); goto end; } if((ssl_load_dh_params(ctx, confs))) { logp("error loading dh params\n"); goto end; } if(init_listen_socket(address, port, rfds) || init_listen_socket(status_address, status_port, sfds)) goto end; if(!(mainas=async_alloc()) || mainas->init(mainas, 0)) goto end; for(i=0; i<LISTEN_SOCKETS && rfds[i]!=-1; i++) { struct asfd *newfd; if(!(newfd=setup_asfd(mainas, "main server socket", &rfds[i]))) goto end; newfd->fdtype=ASFD_FD_SERVER_LISTEN_MAIN; } for(i=0; i<LISTEN_SOCKETS && sfds[i]!=-1; i++) { struct asfd *newfd; if(!(newfd=setup_asfd(mainas, "main server status socket", &sfds[i]))) goto end; newfd->fdtype=ASFD_FD_SERVER_LISTEN_STATUS; } while(!hupreload) { switch(mainas->read_write(mainas)) { case 0: for(asfd=mainas->asfd; asfd; asfd=asfd->next) { if(asfd->new_client) { // Incoming client. asfd->new_client=0; if(process_incoming_client(asfd, ctx, conffile, confs)) goto end; if(!get_int(confs[OPT_FORK])) { gentleshutdown++; ret=1; goto end; } continue; } } break; default: int removed=0; // Maybe one of the fds had a problem. // Find and remove it and carry on if possible. for(asfd=mainas->asfd; asfd; ) { struct asfd *a; if(!asfd->want_to_remove) { asfd=asfd->next; continue; } mainas->asfd_remove(mainas, asfd); logp("%s: disconnected fd %d\n", asfd->desc, asfd->fd); a=asfd->next; asfd_free(&asfd); asfd=a; removed++; } if(removed) break; // If we got here, there was no fd to remove. // It is a fatal error. goto end; } for(asfd=mainas->asfd; asfd; asfd=asfd->next) { if(asfd->fdtype!=ASFD_FD_SERVER_PIPE_READ || !asfd->rbuf->buf) continue; // One of the child processes is giving us information. // Try to append it to any of the status child pipes. for(scfd=mainas->asfd; scfd; scfd=scfd->next) { if(scfd->fdtype!=ASFD_FD_SERVER_PIPE_WRITE) continue; switch(scfd->append_all_to_write_buffer(scfd, asfd->rbuf)) { case APPEND_OK: case APPEND_BLOCKED: break; default: goto end; } } // Free the information, even if we did not manage // to append it. That should be OK, more will be along // soon. iobuf_free_content(asfd->rbuf); } chld_check_for_exiting(mainas); // Leave if we had a SIGUSR1 and there are no children running. if(gentleshutdown) { if(!gentleshutdown_logged) { logp("got SIGUSR2 gentle reload signal\n"); logp("will shut down once children have exited\n"); gentleshutdown_logged++; } // FIX THIS: // found_normal_child=chld_add_fd_to_normal_sets(confs, &fsr, &fse, &mfd); else if(!found_normal_child) { logp("all children have exited - shutting down\n"); break; } } } if(hupreload) logp("got SIGHUP reload signal\n"); ret=0; end: async_asfd_free_all(&mainas); if(ctx) ssl_destroy_ctx(ctx); return ret; }
static int run_server(struct conf *conf, const char *conffile, int *rfd, const char *oldport, const char *oldstatusport) { int ret=0; SSL_CTX *ctx=NULL; int found_normal_child=0; if(!(ctx=ssl_initialise_ctx(conf))) { logp("error initialising ssl ctx\n"); return 1; } if((ssl_load_dh_params(ctx, conf))) { logp("error loading dh params\n"); return 1; } if(!oldport || strcmp(oldport, conf->port)) { close_fd(rfd); if((*rfd=init_listen_socket(conf->port, 1))<0) return 1; } if(conf->status_port && (!oldstatusport || strcmp(oldstatusport, conf->status_port))) { close_fd(&sfd); if((sfd=init_listen_socket(conf->status_port, 0))<0) return 1; } while(!hupreload) { int mfd=-1; fd_set fsr; fd_set fsw; fd_set fse; struct timeval tval; if(sigchld) { chld_check_for_exiting(); sigchld=0; } FD_ZERO(&fsr); FD_ZERO(&fse); tval.tv_sec=1; tval.tv_usec=0; add_fd_to_sets(*rfd, &fsr, NULL, &fse, &mfd); if(sfd>=0) add_fd_to_sets(sfd, &fsr, NULL, &fse, &mfd); // Add read fds of normal children. found_normal_child=chld_add_fd_to_normal_sets(conf, &fsr, &fse, &mfd); // Leave if we had a SIGUSR1 and there are no children // running. if(gentleshutdown) { if(!gentleshutdown_logged) { logp("got SIGUSR2 gentle reload signal\n"); logp("will shut down once children have exited\n"); gentleshutdown_logged++; } else if(!found_normal_child) { logp("all children have exited - shutting down\n"); break; } } if(select(mfd+1, &fsr, NULL, &fse, &tval)<0) { if(errno!=EAGAIN && errno!=EINTR) { logp("select error in normal part of %s: %s\n", __func__, strerror(errno)); ret=1; break; } } if(FD_ISSET(*rfd, &fse)) { // Happens when a client exits. //logp("error on listening socket.\n"); if(!conf->forking) { gentleshutdown++; break; } continue; } if((sfd>=0 && FD_ISSET(sfd, &fse))) { // Happens when a client exits. //logp("error on status socket.\n"); if(!conf->forking) { gentleshutdown++; break; } continue; } if(FD_ISSET(*rfd, &fsr)) { // A normal client is incoming. if(process_incoming_client(*rfd, conf, ctx, conffile, 0 /* not a status client */)) { ret=1; break; } if(!conf->forking) { gentleshutdown++; break; } } if(sfd>=0 && FD_ISSET(sfd, &fsr)) { // A status client is incoming. //printf("status client?\n"); if(process_incoming_client(sfd, conf, ctx, conffile, 1 /* a status client */)) { ret=1; break; } if(!conf->forking) { gentleshutdown++; break; } } if(chld_fd_isset_normal(conf, &fsr, &fse)) { ret=1; break; } // Have a separate select for writing to status server children mfd=-1; FD_ZERO(&fsw); FD_ZERO(&fse); if(!chld_add_fd_to_status_sets(conf, &fsw, &fse, &mfd)) { // Did not find any status server children. // No need to do the select. continue; } // Do not hang around - doing the status stuff is a lower // priority thing than dealing with normal clients. tval.tv_sec=0; tval.tv_usec=500; //printf("try status server\n"); if(select(mfd+1, NULL, &fsw, &fse, &tval)<0) { if(errno!=EAGAIN && errno!=EINTR) { logp("select error in status part of %s: %s\n", __func__, strerror(errno)); ret=1; break; } } if(chld_fd_isset_status(conf, &fsw, &fse)) { ret=1; break; } } if(hupreload) logp("got SIGHUP reload signal\n"); ssl_destroy_ctx(ctx); return ret; }