From 440360723db14fc1f6db72894936aa2a1ac71e86 Mon Sep 17 00:00:00 2001 From: yoe Date: Fri, 26 Oct 2007 12:31:33 +0000 Subject: [PATCH] r294: Delay daemon() call as long as possible, and modify error handling slightly to be more verbose on failure. Modified from Corey Minyard (as was my previous commit) --- cliserv.h | 3 +- nbd-server.c | 193 +++++++++++++++++++++++++++++++--------------------------- 2 files changed, 103 insertions(+), 93 deletions(-) diff --git a/cliserv.h b/cliserv.h index 1d8ecae..49dffca 100644 --- a/cliserv.h +++ b/cliserv.h @@ -96,9 +96,8 @@ void err(const char *s) { s1[maxlen-1] = '\0'; #ifdef ISSERVER syslog(LOG_ERR, "%s", s1); -#else - fprintf(stderr, "Error: %s\n", s1); #endif + fprintf(stderr, "Error: %s\n", s1); exit(1); } diff --git a/nbd-server.c b/nbd-server.c index f9691df..044e6d9 100644 --- a/nbd-server.c +++ b/nbd-server.c @@ -139,7 +139,7 @@ gchar* rungroup=NULL; **/ #define OFFT_MAX ~((off_t)1<<(sizeof(off_t)*8-1)) #define LINELEN 256 /**< Size of static buffer used to read the - authorization file (yuck) */ + authorization file (yuck) */ #define BUFSIZE (1024*1024) /**< Size of buffer that can hold requests */ #define DIFFPAGESIZE 4096 /**< diff file uses those chunks */ #define F_READONLY 1 /**< flag to tell us a file is readonly */ @@ -1365,6 +1365,96 @@ void destroy_pid_t(gpointer data) { } /** + * Loop through the available servers, and serve them. Never returns. + **/ +int serveloop(GArray* servers) G_GNUC_NORETURN { + struct sockaddr_in addrin; + socklen_t addrinlen=sizeof(addrin); + SERVER *serve; + int i; + int max; + int sock; + fd_set mset; + fd_set rset; + struct timeval tv; + + /* + * Set up the master fd_set. The set of descriptors we need + * to select() for never changes anyway and it buys us a *lot* + * of time to only build this once. However, if we ever choose + * to not fork() for clients anymore, we may have to revisit + * this. + */ + max=0; + FD_ZERO(&mset); + for(i=0;ilen;i++) { + sock=(g_array_index(servers, SERVER, i)).socket; + FD_SET(sock, &mset); + max=sock>max?sock:max; + } + for(;;) { + CLIENT *client; + int net; + pid_t *pid; + + memcpy(&rset, &mset, sizeof(fd_set)); + tv.tv_sec=0; + tv.tv_usec=500; + if(select(max+1, &rset, NULL, NULL, &tv)>0) { + DEBUG("accept, "); + for(i=0;ilen;i++) { + serve=&(g_array_index(servers, SERVER, i)); + if(FD_ISSET(serve->socket, &rset)) { + if ((net=accept(serve->socket, (struct sockaddr *) &addrin, &addrinlen)) < 0) + err("accept: %m"); + + client = g_malloc(sizeof(CLIENT)); + client->server=serve; + client->exportsize=OFFT_MAX; + client->net=net; + set_peername(net, client); + if (!authorized_client(client)) { + msg2(LOG_INFO,"Unauthorized client") ; + close(net); + continue; + } + msg2(LOG_INFO,"Authorized client") ; + pid=g_malloc(sizeof(pid_t)); +#ifndef NOFORK + if ((*pid=fork())<0) { + msg3(LOG_INFO,"Could not fork (%s)",strerror(errno)) ; + close(net); + continue; + } + if (*pid>0) { /* parent */ + close(net); + g_hash_table_insert(children, pid, pid); + continue; + } + /* child */ + g_hash_table_destroy(children); + for(i=0;ilen;i++) { + serve=g_array_index(servers, SERVER*, i); + close(serve->socket); + } + /* FALSE does not free the + actual data. This is required, + because the client has a + direct reference into that + data, and otherwise we get a + segfault... */ + g_array_free(servers, FALSE); +#endif // NOFORK + msg2(LOG_INFO,"Starting to serve"); + serveconnection(client); + exit(EXIT_SUCCESS); + } + } + } + } +} + +/** * Go daemon (unless we specified at compile time that we didn't want this) * @param serve the first server of our configuration. If its port is zero, * then do not daemonize, because we're doing inetd then. This parameter @@ -1402,6 +1492,17 @@ void daemonize(SERVER* serve) { #define daemonize(serve) #endif /* !defined(NODAEMON) && !defined(NOFORK) */ +/* + * Everything beyond this point (in the file) is run in non-daemon mode. + * The stuff above daemonize() isn't. + */ + +void serve_err(SERVER* serve, const char* msg) G_GNUC_NORETURN { + g_message("Export of %s on port %d failed:", serve->exportname, + serve->port); + err(msg); +} + /** * Connect a server's socket. * @@ -1483,96 +1584,6 @@ void setup_servers(GArray* servers) { } /** - * Loop through the available servers, and serve them. - **/ -int serveloop(GArray* servers) { - struct sockaddr_in addrin; - socklen_t addrinlen=sizeof(addrin); - SERVER *serve; - int i; - int max; - int sock; - fd_set mset; - fd_set rset; - struct timeval tv; - - /* - * Set up the master fd_set. The set of descriptors we need - * to select() for never changes anyway and it buys us a *lot* - * of time to only build this once. However, if we ever choose - * to not fork() for clients anymore, we may have to revisit - * this. - */ - max=0; - FD_ZERO(&mset); - for(i=0;ilen;i++) { - sock=(g_array_index(servers, SERVER, i)).socket; - FD_SET(sock, &mset); - max=sock>max?sock:max; - } - for(;;) { - CLIENT *client; - int net; - pid_t *pid; - - memcpy(&rset, &mset, sizeof(fd_set)); - tv.tv_sec=0; - tv.tv_usec=500; - if(select(max+1, &rset, NULL, NULL, &tv)>0) { - DEBUG("accept, "); - for(i=0;ilen;i++) { - serve=&(g_array_index(servers, SERVER, i)); - if(FD_ISSET(serve->socket, &rset)) { - if ((net=accept(serve->socket, (struct sockaddr *) &addrin, &addrinlen)) < 0) - err("accept: %m"); - - client = g_malloc(sizeof(CLIENT)); - client->server=serve; - client->exportsize=OFFT_MAX; - client->net=net; - set_peername(net, client); - if (!authorized_client(client)) { - msg2(LOG_INFO,"Unauthorized client") ; - close(net); - continue; - } - msg2(LOG_INFO,"Authorized client") ; - pid=g_malloc(sizeof(pid_t)); -#ifndef NOFORK - if ((*pid=fork())<0) { - msg3(LOG_INFO,"Could not fork (%s)",strerror(errno)) ; - close(net); - continue; - } - if (*pid>0) { /* parent */ - close(net); - g_hash_table_insert(children, pid, pid); - continue; - } - /* child */ - g_hash_table_destroy(children); - for(i=0;ilen;i++) { - serve=g_array_index(servers, SERVER*, i); - close(serve->socket); - } - /* FALSE does not free the - actual data. This is required, - because the client has a - direct reference into that - data, and otherwise we get a - segfault... */ - g_array_free(servers, FALSE); -#endif // NOFORK - msg2(LOG_INFO,"Starting to serve"); - serveconnection(client); - exit(EXIT_SUCCESS); - } - } - } - } -} - -/** * Set up user-ID and/or group-ID **/ void dousers(void) { -- 1.7.10.4