commit - 6a5431286b29f74a150aed3c2cb14c6744401e11
commit + bb32659f4666bd508118a9e15238bb69471b3b14
blob - 90eb143afce8e50c7ba53d141294ca8616d7a074
blob + f5f240b7d414b6737f10eb222651623aef0067e3
--- gotwebd/config.c
+++ gotwebd/config.c
strlcpy(env->httpd_chroot, D_HTTPD_CHROOT, sizeof(env->httpd_chroot));
- env->prefork_gotwebd = GOTWEBD_NUMPROC;
+ env->prefork = GOTWEBD_NUMPROC;
env->server_cnt = 0;
TAILQ_INIT(&env->servers);
TAILQ_INIT(&env->sockets);
__func__, PRIV_FDS__MAX + GOTWEB_PACK_NUM_TEMPFILES);
for (i = 0; i < PRIV_FDS__MAX + GOTWEB_PACK_NUM_TEMPFILES; i++) {
- for (j = 0; j < env->nserver; ++j) {
+ for (j = 0; j < env->prefork; j++) {
fd = got_opentempfd();
if (fd == -1)
fatal("got_opentemp");
blob - 0f92cc1b3d0cdafc2c5d0232698fed51772579fe
blob + 58a88e7f43f9c77ff11bef8420d7ec926c4ffb56
--- gotwebd/fcgi.c
+++ gotwebd/fcgi.c
process_request(struct request *c)
{
struct gotwebd *env = gotwebd_env;
+ struct imsgev *iev_gotweb;
int ret, i;
struct request ic;
ic.priv_fd[i] = -1;
ic.fd = -1;
- ret = imsg_compose_event(env->iev_gotweb, GOTWEBD_IMSG_REQ_PROCESS,
+ /* Round-robin requests across gotweb processes. */
+ iev_gotweb = &env->iev_gotweb[env->gotweb_cur];
+ env->gotweb_cur = (env->gotweb_cur + 1) % env->prefork;
+
+ ret = imsg_compose_event(iev_gotweb, GOTWEBD_IMSG_REQ_PROCESS,
GOTWEBD_PROC_SERVER, -1, c->fd, &ic, sizeof(ic));
if (ret == -1) {
log_warn("imsg_compose_event");
- close(c->fd);
+ return;
}
c->fd = -1;
blob - 03f8e6941798467f7ecdd2e1de64cdc88bf28422
blob + cc891f8eb78a1444fed0684e79e52a496a2008c7
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
static void
gotweb_shutdown(void)
{
+ struct gotwebd *env = gotwebd_env;
+ int i;
+
imsgbuf_clear(&gotwebd_env->iev_parent->ibuf);
free(gotwebd_env->iev_parent);
- if (gotwebd_env->iev_server) {
- imsgbuf_clear(&gotwebd_env->iev_server->ibuf);
- free(gotwebd_env->iev_server);
- }
+
+ for (i = 0; i < env->server_cnt - env->servers_pending; i++)
+ imsgbuf_clear(&gotwebd_env->iev_server[i].ibuf);
+ free(gotwebd_env->iev_server);
while (!TAILQ_EMPTY(&gotwebd_env->servers)) {
struct server *srv;
{
struct server *srv;
const struct got_error *error;
+ int i;
- if (env->iev_server == NULL)
+ if (env->servers_pending != 0)
fatal("server process not connected");
#ifndef PROFILE
if (unveil(NULL, NULL) == -1)
fatal("unveil");
- event_add(&env->iev_server->ev, NULL);
+ for (i = 0; i < env->server_cnt; i++)
+ event_add(&env->iev_server[i].ev, NULL);
}
static void
struct imsgev *iev;
int fd;
- if (env->iev_server != NULL) {
- log_warn("server pipe already received");
+ if (env->servers_pending <= 0) {
+ log_warn("server pipes already received");
return;
}
if (fd == -1)
fatalx("invalid server pipe fd");
- iev = calloc(1, sizeof(*iev));
- if (iev == NULL)
- fatal("calloc");
-
+ iev = &env->iev_server[env->servers_pending - 1];
if (imsgbuf_init(&iev->ibuf, fd) == -1)
fatal("imsgbuf_init");
imsgbuf_allow_fdpass(&iev->ibuf);
event_set(&iev->ev, fd, EV_READ, gotweb_dispatch_server, iev);
imsg_event_add(iev);
- env->iev_server = iev;
+ env->servers_pending--;
}
static void
sockets_rlimit(-1);
- if ((env->iev_parent = malloc(sizeof(*env->iev_parent))) == NULL)
- fatal("malloc");
+ env->iev_parent = calloc(1, sizeof(*env->iev_parent));
+ if (env->iev_parent == NULL)
+ fatal("calloc");
if (imsgbuf_init(&env->iev_parent->ibuf, fd) == -1)
fatal("imsgbuf_init");
imsgbuf_allow_fdpass(&env->iev_parent->ibuf);
env->iev_parent);
event_add(&env->iev_parent->ev, NULL);
+ if (env->server_cnt <= 0)
+ fatalx("invalid server count: %d", env->server_cnt);
+ env->iev_server = calloc(env->server_cnt, sizeof(*env->iev_server));
+ if (env->iev_server == NULL)
+ fatal("calloc");
+ env->servers_pending = env->server_cnt;
+
signal(SIGPIPE, SIG_IGN);
signal_set(&sighup, SIGHUP, gotweb_sighdlr, env);
blob - 7e6aaf321f8905c1854851da0b0ffd2335b49ea9
blob + 68ffcc1638c3db490e1b14e4ab1194f8dc7776db
--- gotwebd/gotwebd.c
+++ gotwebd/gotwebd.c
size_t i;
int ret = 0;
- for (i = 0; i < env->nserver; ++i) {
+ for (i = 0; i < env->server_cnt; ++i) {
ret = send_imsg(&env->iev_server[i], type, fd, data, len);
if (ret)
break;
size_t i;
int ret = 0;
- for (i = 0; i < env->nserver; ++i) {
+ for (i = 0; i < env->prefork; i++) {
ret = send_imsg(&env->iev_gotweb[i], type, fd, data, len);
if (ret)
break;
enum gotwebd_proc_type proc_type, const char *username,
void (*handler)(int, short, void *))
{
- const char *argv[9];
+ const char *argv[10];
int argc = 0;
int p[2];
pid_t pid;
argv[argc++] = argv0;
if (proc_type == GOTWEBD_PROC_SERVER) {
+ char *s;
+
argv[argc++] = "-S";
argv[argc++] = username;
+ if (asprintf(&s, "-S%d", env->prefork) == -1)
+ fatal("asprintf");
+ argv[argc++] = s;
} else if (proc_type == GOTWEBD_PROC_GOTWEB) {
+ char *s;
+
argv[argc++] = "-G";
argv[argc++] = username;
+ if (asprintf(&s, "-G%d", env->server_cnt) == -1)
+ fatal("asprintf");
+ argv[argc++] = s;
}
if (strcmp(env->gotwebd_conffile, GOTWEBD_CONF) != 0) {
argv[argc++] = "-f";
const char *www_username = GOTWEBD_WWW_USER;
gid_t gotwebd_groups[NGROUPS_MAX];
gid_t www_gid;
- const char *argv0;
+ const char *argv0, *errstr;
if ((argv0 = argv[0]) == NULL)
argv0 = "gotwebd";
break;
case 'G':
proc_type = GOTWEBD_PROC_GOTWEB;
- gotwebd_username = optarg;
+ i = strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr)
+ gotwebd_username = optarg;
+ else
+ env->server_cnt = i;
break;
case 'f':
conffile = optarg;
break;
case 'S':
proc_type = GOTWEBD_PROC_SERVER;
- gotwebd_username = optarg;
+ i = strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr)
+ gotwebd_username = optarg;
+ else
+ env->prefork = i;
break;
case 'v':
if (env->gotwebd_verbose < 3)
evb = event_init();
- env->nserver = env->prefork_gotwebd;
- env->iev_server = calloc(env->nserver, sizeof(*env->iev_server));
+ env->iev_server = calloc(env->server_cnt, sizeof(*env->iev_server));
if (env->iev_server == NULL)
fatal("calloc");
- env->iev_gotweb = calloc(env->nserver, sizeof(*env->iev_gotweb));
+ env->iev_gotweb = calloc(env->prefork, sizeof(*env->iev_gotweb));
if (env->iev_gotweb == NULL)
fatal("calloc");
- for (i = 0; i < env->nserver; ++i) {
+ for (i = 0; i < env->server_cnt; ++i) {
spawn_process(env, argv0, &env->iev_server[i],
GOTWEBD_PROC_SERVER, gotwebd_username,
gotwebd_dispatch_server);
+ }
+ for (i = 0; i < env->prefork; ++i) {
spawn_process(env, argv0, &env->iev_gotweb[i],
GOTWEBD_PROC_GOTWEB, gotwebd_username,
gotwebd_dispatch_gotweb);
{
struct imsgev *iev1, *iev2;
int pipe[2];
- int i;
+ int i, j;
- for (i = 0; i < env->nserver; i++) {
+ for (i = 0; i < env->server_cnt; i++) {
iev1 = &env->iev_server[i];
- iev2 = &env->iev_gotweb[i];
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe) == -1)
- fatal("socketpair");
+ for (j = 0; j < env->prefork; j++) {
+ iev2 = &env->iev_gotweb[j];
- if (send_imsg(iev1, GOTWEBD_IMSG_CTL_PIPE, pipe[0], NULL, 0))
- fatal("send_imsg");
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
+ pipe) == -1)
+ fatal("socketpair");
- if (send_imsg(iev2, GOTWEBD_IMSG_CTL_PIPE, pipe[1], NULL, 0))
- fatal("send_imsg");
+ if (send_imsg(iev1, GOTWEBD_IMSG_CTL_PIPE, pipe[0],
+ NULL, 0))
+ fatal("send_imsg");
+
+ if (send_imsg(iev2, GOTWEBD_IMSG_CTL_PIPE, pipe[1],
+ NULL, 0))
+ fatal("send_imsg");
+ }
}
}
struct socket *sock;
/* gotweb need to reload its config. */
- env->servers_pending = env->prefork_gotwebd;
- env->gotweb_pending = env->prefork_gotwebd;
+ env->servers_pending = env->server_cnt;
+ env->gotweb_pending = env->prefork;
/* send our gotweb servers */
TAILQ_FOREACH(srv, &env->servers, entry) {
pid_t pid;
int i, status;
- for (i = 0; i < env->nserver; ++i) {
+ for (i = 0; i < env->server_cnt; ++i) {
event_del(&env->iev_server[i].ev);
imsgbuf_clear(&env->iev_server[i].ibuf);
close(env->iev_server[i].ibuf.fd);
}
free(env->iev_server);
- for (i = 0; i < env->nserver; ++i) {
+ for (i = 0; i < env->prefork; ++i) {
event_del(&env->iev_gotweb[i].ev);
imsgbuf_clear(&env->iev_gotweb[i].ibuf);
close(env->iev_gotweb[i].ibuf.fd);
blob - 562d13bf30399506f8f4f2c9eca0d103cf6e5cdd
blob + 27e26b6abdbf45670ce6655d54bb9c73a73074ea
--- gotwebd/gotwebd.conf.5
+++ gotwebd/gotwebd.conf.5
must be absolute, it should usually point inside the web server's chroot
directory such that the web server can access the socket.
.It Ic prefork Ar number
-Run the specified number of server processes.
+Spawn enough processes such that
+.Ar number
+requests can be handled in parallel.
+By default,
.Xr gotwebd 8
-runs 3 server processes by default.
+will handle up to 3 requests in parallel.
+The maximum allowed is 32.
.It Ic user Ar user
Set the
.Ar user
blob - 888f71c5b60cbc3697f03efa568436627738f7dc
blob + b6e69183db3f973c8495e874e281a672de6f3f4c
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
struct imsgev *iev_parent;
struct imsgev *iev_server;
struct imsgev *iev_gotweb;
- size_t nserver;
- uint16_t prefork_gotwebd;
+ uint16_t prefork;
int servers_pending;
int gotweb_pending;
+ int gotweb_cur;
int server_cnt;
blob - 28cc307a5e9e04f189781f0f3c7c189a87700a17
blob + a985c4c448a29a5e34d9a497c1736397cd5ed2af
--- gotwebd/parse.y
+++ gotwebd/parse.y
$2 <= 0 ? "too small" : "too large", $2);
YYERROR;
}
- gotwebd->prefork_gotwebd = $2;
+ gotwebd->prefork = $2;
}
| CHROOT STRING {
if (*$2 == '\0') {
blob - 2d3df9cf55d52a941f6e5bb9603401f44514b73d
blob + b8454b51d4dcc561ebb7dcdda35495534adc5707
--- gotwebd/sockets.c
+++ gotwebd/sockets.c
sockets_rlimit(-1);
- if ((env->iev_parent = malloc(sizeof(*env->iev_parent))) == NULL)
- fatal("malloc");
+ env->iev_parent = calloc(1, sizeof(*env->iev_parent));
+ if (env->iev_parent == NULL)
+ fatal("calloc");
if (imsgbuf_init(&env->iev_parent->ibuf, fd) == -1)
fatal("imsgbuf_init");
imsgbuf_allow_fdpass(&env->iev_parent->ibuf);
env->iev_parent);
event_add(&env->iev_parent->ev, NULL);
+ if (env->prefork <= 0)
+ fatalx("invalid prefork count: %d", env->prefork);
+ env->iev_gotweb = calloc(env->prefork, sizeof(*env->iev_gotweb));
+ if (env->iev_gotweb == NULL)
+ fatal("calloc");
+ env->gotweb_pending = env->prefork;
+
signal(SIGPIPE, SIG_IGN);
signal_set(&sighup, SIGHUP, sockets_sighdlr, env);
sockets_launch(struct gotwebd *env)
{
struct socket *sock;
+ int i;
- if (env->iev_gotweb == NULL)
+ if (env->gotweb_pending != 0)
fatal("gotweb process not connected");
TAILQ_FOREACH(sock, &gotwebd_env->sockets, entry) {
if (pledge("stdio inet sendfd", NULL) == -1)
fatal("pledge");
#endif
- event_add(&env->iev_gotweb->ev, NULL);
+ for (i = 0; i < env->prefork; i++)
+ event_add(&env->iev_gotweb[i].ev, NULL);
}
struct imsgev *iev;
int fd;
- if (env->iev_gotweb != NULL) {
+ if (env->gotweb_pending <= 0) {
log_warn("gotweb pipe already received");
return;
}
if (fd == -1)
fatalx("invalid gotweb pipe fd");
- iev = calloc(1, sizeof(*iev));
- if (iev == NULL)
- fatal("calloc");
-
+ iev = &env->iev_gotweb[env->gotweb_pending - 1];
if (imsgbuf_init(&iev->ibuf, fd) == -1)
fatal("imsgbuf_init");
imsgbuf_allow_fdpass(&iev->ibuf);
event_set(&iev->ev, fd, EV_READ, server_dispatch_gotweb, iev);
imsg_event_add(iev);
- env->iev_gotweb = iev;
+ env->gotweb_pending--;
}
static void
static void
sockets_shutdown(void)
{
+ int i;
+
/* clean servers */
while (!TAILQ_EMPTY(&gotwebd_env->servers)) {
struct server *srv;
imsgbuf_clear(&gotwebd_env->iev_parent->ibuf);
free(gotwebd_env->iev_parent);
- imsgbuf_clear(&gotwebd_env->iev_gotweb->ibuf);
+ for (i = 0; i < gotwebd_env->prefork; i++)
+ imsgbuf_clear(&gotwebd_env->iev_gotweb[i].ibuf);
free(gotwebd_env->iev_gotweb);
free(gotwebd_env);