Commit c60b4f81 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

We clean the child process of unwanted open filedescriptors, but this can

take time if there are hundreds of thousands of possible filedescriptors.

Instead do it once, right at startup in the manager process, and then
keep track of the fd's we use there, and have the child clean only
up to the max seen, with an allowance for filedescriptors held by
libraries (syslog, resolver, pidfiles etc)

Fixes	#699



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@4648 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 11e0df2c
......@@ -46,6 +46,7 @@ extern int exit_status;
extern pid_t child_pid;
void MGT_Run(void);
void mgt_stop_child(void);
void mgt_got_fd(int fd);
/* mgt_cli.c */
......
......@@ -71,6 +71,7 @@ SVNID("$Id$")
pid_t child_pid = -1;
static struct vbitmap *fd_map;
static int child_cli_in = -1;
......@@ -97,6 +98,33 @@ static struct vev *ev_poker;
static struct vev *ev_listen;
static struct vlu *vlu;
/*--------------------------------------------------------------------
* Track the highest file descriptor the parent knows is being used.
*
* This allows the child process to clean/close only a small fraction
* of the possible file descriptors after exec(2).
*
* This is likely to a bit on the low side, as libc and other libraries
* has a tendency to cache file descriptors (syslog, resolver, etc.)
* so we add a margin of 100 fds.
*/
static int mgt_max_fd;
#define CLOSE_FD_UP_TO (mgt_max_fd + 100)
void
mgt_got_fd(int fd)
{
/*
* Assert > 0, to catch bogus opens, we know where stdin goes
* in the master process.
*/
assert(fd > 0);
if (fd > mgt_max_fd)
mgt_max_fd = fd;
}
/*--------------------------------------------------------------------
* A handy little function
*/
......@@ -270,7 +298,7 @@ start_child(struct cli *cli)
unsigned u;
char *p;
struct vev *e;
int i, j, cp[2];
int i, cp[2];
if (child_state != CH_STOPPED && child_state != CH_DIED)
return;
......@@ -337,13 +365,10 @@ start_child(struct cli *cli)
/* Close anything we shouldn't know about */
closelog();
printf("Closed fds:");
j = getdtablesize();
for (i = STDERR_FILENO + 1; i < j; i++) {
for (i = STDERR_FILENO + 1; i < CLOSE_FD_UP_TO; i++) {
if (vbit_test(fd_map, i))
continue;
if (close(i) == 0)
printf(" %d", i);
(void)(close(i) == 0);
}
printf("\n");
......
......@@ -301,6 +301,7 @@ mcf_auth(struct cli *cli, const char *const *av, void *priv)
cli_result(cli, CLIS_CANT);
return;
}
mgt_got_fd(fd);
CLI_response(fd, cli->challenge, buf);
AZ(close(fd));
if (strcasecmp(buf, av[2])) {
......@@ -488,6 +489,7 @@ telnet_accept(const struct vev *ev, int what)
if (i < 0)
return (0);
mgt_got_fd(i);
tn = telnet_new(i);
vsb = sock_id("telnet", i);
mgt_cli_setup(i, i, 0, vsb_data(vsb), telnet_close, tn);
......@@ -508,6 +510,7 @@ mgt_cli_secret(const char *S_arg)
fprintf(stderr, "Can not open secret-file \"%s\"\n", S_arg);
exit (2);
}
mgt_got_fd(fd);
i = read(fd, buf, sizeof buf);
if (i == 0) {
fprintf(stderr, "Empty secret-file \"%s\"\n", S_arg);
......@@ -623,6 +626,8 @@ Marg_poker(const struct vev *e, int what)
if (s < 0)
return (0);
mgt_got_fd(s);
M_conn = vev_new();
AN(M_conn);
M_conn->callback = Marg_poker;
......
......@@ -164,6 +164,7 @@ run_vcc(void *priv)
fprintf(stderr, "Cannot open %s", vp->sf);
exit (1);
}
mgt_got_fd(fd);
l = strlen(csrc);
i = write(fd, csrc, l);
if (i != l) {
......
......@@ -424,6 +424,15 @@ main(int argc, char * const *argv)
struct pidfh *pfh = NULL;
char dirname[1024];
/*
* Start out by closing all unwanted file descriptors we might
* have inherited from sloppy process control daemons.
*/
for (o = getdtablesize(); o > STDERR_FILENO; o--)
(void)close(o);
mgt_got_fd(STDERR_FILENO);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment