process: associate open connections with clients

This commit is contained in:
Justin Maggard 2014-06-09 18:48:49 -07:00
parent e9a653d6e8
commit a46a8e5e89
5 changed files with 102 additions and 16 deletions

View File

@ -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[];

View File

@ -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)

View File

@ -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);
}
}

View File

@ -30,6 +30,16 @@
#define __PROCESS_H__
#include <unistd.h>
#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__

View File

@ -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,
"<h3>Connected clients</h3>"
"<table border=1 cellpadding=10>"
"<tr><td>ID</td><td>Type</td><td>IP Address</td><td>HW Address</td></tr>");
"<tr><td>ID</td><td>Type</td><td>IP Address</td><td>HW Address</td><td>Connections</td></tr>");
for (i = 0; i < CLIENT_CACHE_SLOTS; i++)
{
if (!clients[i].addr.s_addr)
continue;
strcatf(&str, "<tr><td>%d</td><td>%s</td><td>%s</td><td>%02X:%02X:%02X:%02X:%02X:%02X</td></tr>",
strcatf(&str, "<tr><td>%d</td><td>%s</td><td>%s</td><td>%02X:%02X:%02X:%02X:%02X:%02X</td><td>%d</td></tr>",
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, "</table></BODY></HTML>\r\n");
strcatf(&str, "</table>");
strcatf(&str, "<br>%d connection%s currently open<br>", number_of_children, (number_of_children == 1 ? "" : "s"));
strcatf(&str, "</BODY></HTML>\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);