From a46a8e5e896b32eeef89f814b85fc9d48c8e210c Mon Sep 17 00:00:00 2001 From: Justin Maggard Date: Mon, 9 Jun 2014 18:48:49 -0700 Subject: [PATCH] process: associate open connections with clients --- clients.h | 1 + minidlna.c | 14 +++++++++-- process.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++---- process.h | 17 +++++++++++++- upnphttp.c | 18 ++++++++------- 5 files changed, 102 insertions(+), 16 deletions(-) diff --git a/clients.h b/clients.h index d904ed0..dc766c6 100644 --- a/clients.h +++ b/clients.h @@ -93,6 +93,7 @@ struct client_cache_s { unsigned char mac[6]; struct client_type_s *type; time_t age; + int connections; }; extern struct client_type_s client_types[]; diff --git a/minidlna.c b/minidlna.c index c8eed5b..4ee55c1 100644 --- a/minidlna.c +++ b/minidlna.c @@ -372,7 +372,7 @@ rescan: #if USE_FORK scanning = 1; sqlite3_close(db); - *scanner_pid = process_fork(); + *scanner_pid = fork(); open_db(&db); if (*scanner_pid == 0) /* child (scanner) process */ { @@ -969,6 +969,13 @@ init(int argc, char **argv) DPRINTF(E_FATAL, L_GENERAL, "Failed to switch to uid '%d'. [%s] EXITING.\n", uid, strerror(errno)); + children = calloc(runtime_vars.max_connections, sizeof(struct child)); + if (!children) + { + DPRINTF(E_ERROR, L_GENERAL, "Allocation failed\n"); + return 1; + } + return 0; } @@ -1285,7 +1292,10 @@ main(int argc, char **argv) shutdown: /* kill the scanner */ if (scanning && scanner_pid) - kill(scanner_pid, 9); + kill(scanner_pid, SIGKILL); + + /* kill other child processes */ + process_reap_children(); /* close out open sockets */ while (upnphttphead.lh_first != NULL) diff --git a/process.c b/process.c index 00b802b..96ec1c3 100644 --- a/process.c +++ b/process.c @@ -43,10 +43,47 @@ #include "config.h" #include "log.h" -static int number_of_children = 0; +struct child *children = NULL; +int number_of_children = 0; + +static void +add_process_info(pid_t pid, struct client_cache_s *client) +{ + struct child *child; + int i; + + for (i = 0; i < runtime_vars.max_connections; i++) + { + child = children+i; + if (child->pid) + continue; + child->pid = pid; + child->client = client; + child->age = time(NULL); + break; + } +} + +static inline void +remove_process_info(pid_t pid) +{ + struct child *child; + int i; + + for (i = 0; i < runtime_vars.max_connections; i++) + { + child = children+i; + if (child->pid != pid) + continue; + child->pid = 0; + if (child->client) + child->client->connections--; + break; + } +} pid_t -process_fork(void) +process_fork(struct client_cache_s *client) { if (number_of_children >= runtime_vars.max_connections) { @@ -58,7 +95,13 @@ process_fork(void) pid_t pid = fork(); if (pid > 0) - ++number_of_children; + { + number_of_children++; + if (client) + client->connections++; + add_process_info(pid, client); + } + return pid; } @@ -76,7 +119,8 @@ process_handle_child_termination(int signal) else break; } - --number_of_children; + number_of_children--; + remove_process_info(pid); } } @@ -87,7 +131,7 @@ process_daemonize(void) #ifndef USE_DAEMON int i; - switch(process_fork()) + switch(fork()) { /* fork error */ case -1: @@ -157,3 +201,17 @@ process_check_if_running(const char *fname) return 0; } + +void +process_reap_children(void) +{ + struct child *child; + int i; + + for (i = 0; i < runtime_vars.max_connections; i++) + { + child = children+i; + if (child->pid) + kill(child->pid, SIGKILL); + } +} diff --git a/process.h b/process.h index 7fa7682..713c92c 100644 --- a/process.h +++ b/process.h @@ -30,6 +30,16 @@ #define __PROCESS_H__ #include +#include "clients.h" + +struct child { + pid_t pid; + time_t age; + struct client_cache_s *client; +}; + +extern struct child *children; +extern int number_of_children; /** * Fork a new child (just like fork()) but keep track of how many childs are @@ -37,7 +47,7 @@ * @return -1 if it couldn't fork, 0 in the child process, the pid of the * child process in the parent process. */ -pid_t process_fork(void); +pid_t process_fork(struct client_cache_s *client); /** * Handler to be called upon receiving SIGCHLD. This signal is received by the @@ -63,4 +73,9 @@ int process_daemonize(void); */ int process_check_if_running(const char *fname); +/** + * Kill all child processes + */ +void process_reap_children(void); + #endif // __PROCESS_H__ diff --git a/upnphttp.c b/upnphttp.c index d8b6d29..e3a21bd 100644 --- a/upnphttp.c +++ b/upnphttp.c @@ -83,8 +83,7 @@ #include "sendfile.h" -//#define MAX_BUFFER_SIZE 4194304 // 4MB -- Too much? -#define MAX_BUFFER_SIZE 2147483647 // 2GB -- Too much? +#define MAX_BUFFER_SIZE 2147483647 #define MIN_BUFFER_SIZE 65536 #include "icons.c" @@ -615,17 +614,20 @@ SendResp_presentation(struct upnphttp * h) strcatf(&str, "

Connected clients

" "" - ""); + ""); for (i = 0; i < CLIENT_CACHE_SLOTS; i++) { if (!clients[i].addr.s_addr) continue; - strcatf(&str, "", + strcatf(&str, "", i, clients[i].type->name, inet_ntoa(clients[i].addr), clients[i].mac[0], clients[i].mac[1], clients[i].mac[2], - clients[i].mac[3], clients[i].mac[4], clients[i].mac[5]); + clients[i].mac[3], clients[i].mac[4], clients[i].mac[5], clients[i].connections); } - strcatf(&str, "
IDTypeIP AddressHW Address
IDTypeIP AddressHW AddressConnections
%d%s%s%02X:%02X:%02X:%02X:%02X:%02X
%d%s%s%02X:%02X:%02X:%02X:%02X:%02X%d
\r\n"); + strcatf(&str, ""); + + strcatf(&str, "
%d connection%s currently open
", number_of_children, (number_of_children == 1 ? "" : "s")); + strcatf(&str, "\r\n"); BuildResp_upnphttp(h, str.data, str.off); SendResp_upnphttp(h); @@ -1633,7 +1635,7 @@ SendResp_resizedimg(struct upnphttp * h, char * object) #if USE_FORK pid_t newpid = 0; - newpid = process_fork(); + newpid = process_fork(h->req_client); if( newpid > 0 ) { CloseSocket_upnphttp(h); @@ -1875,7 +1877,7 @@ SendResp_dlnafile(struct upnphttp *h, char *object) sqlite3_free_table(result); } #if USE_FORK - newpid = process_fork(); + newpid = process_fork(h->req_client); if( newpid > 0 ) { CloseSocket_upnphttp(h);