diff --git a/README.md b/README.md index b2e3c56..e86d862 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ A very flexible, lightweight and fully asynchronous HTTP server library based on * Support IPv6 * Support plugin * Support upload large file +* Support multi-process model - The same multi-process model as Nginx * Flexible - you can easily extend your application to have HTTP/HTTPS services * Code structure is concise and understandable, also suitable for learning diff --git a/README_ZH.md b/README_ZH.md index 454c1a3..61a4bb6 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -33,6 +33,7 @@ * 支持 IPv6 * 支持插件 * 支持上传大文件 +* 支持多进程模型 - 和 Nginx 一样的多进程模型 * 可伸缩 - 你可以非常方便的扩展你的应用程序,使之具备HTTP/HTTPS服务 * 代码结构简洁通俗易懂,亦适合学习 diff --git a/example/example.c b/example/example.c index f54f8eb..b7f3223 100644 --- a/example/example.c +++ b/example/example.c @@ -196,6 +196,8 @@ int main(int argc, char **argv) goto err; #endif + srv->start_worker(srv, -1); /* -1 means automatically to available CPUs */ + srv->set_docroot(srv, docroot); srv->set_index_page(srv, index_page); diff --git a/src/uhttpd.c b/src/uhttpd.c index 70358db..e68dc9e 100644 --- a/src/uhttpd.c +++ b/src/uhttpd.c @@ -32,6 +32,7 @@ #ifdef HAVE_DLOPEN #include #endif +#include #include "uhttpd_internal.h" #include "connection.h" @@ -100,7 +101,8 @@ static void uh_accept_cb(struct ev_loop *loop, struct ev_io *w, int revents) sock = accept4(srv->sock, (struct sockaddr *)&addr, &addr_len, SOCK_NONBLOCK | SOCK_CLOEXEC); if (sock < 0) { - uh_log_err("accept: %s\n", strerror(errno)); + if (errno != EAGAIN) + uh_log_err("accept: %s\n", strerror(errno)); return; } @@ -123,6 +125,43 @@ static void uh_accept_cb(struct ev_loop *loop, struct ev_io *w, int revents) srv->conns = conn; } +static void uh_start_accept(struct uh_server_internal *srv) +{ + ev_io_init(&srv->ior, uh_accept_cb, srv->sock, EV_READ); + ev_io_start(srv->loop, &srv->ior); +} + +static void uh_stop_accept(struct uh_server_internal *srv) +{ + ev_io_stop(srv->loop, &srv->ior); +} + +static void uh_start_worker(struct uh_server *srv, int n) +{ + struct uh_server_internal *srvi = (struct uh_server_internal *)srv; + pid_t pid; + int i; + + if (n < 0) + n = get_nprocs(); + + if (n > 0) + uh_stop_accept(srvi); + + for (i = 0; i < n; i++) { + pid = fork(); + switch (pid) { + case -1: + uh_log_err("fork: %s\n", strerror(errno)); + return; + case 0: + ev_loop_fork(srvi->loop); + uh_start_accept(srvi); + return; + } + } +} + struct uh_server *uh_server_new(struct ev_loop *loop, const char *host, int port) { struct uh_server *srv; @@ -345,6 +384,7 @@ int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host srvi->loop = loop ? loop : EV_DEFAULT; srvi->sock = sock; srv->free = uh_server_free; + srv->start_worker = uh_start_worker; #if UHTTPD_SSL_SUPPORT srv->ssl_init = uh_server_ssl_init; @@ -358,8 +398,7 @@ int uh_server_init(struct uh_server *srv, struct ev_loop *loop, const char *host srv->set_docroot = uh_set_docroot; srv->set_index_page = uh_set_index_page; - ev_io_init(&srvi->ior, uh_accept_cb, sock, EV_READ); - ev_io_start(srvi->loop, &srvi->ior); + uh_start_accept(srvi); return 0; diff --git a/src/uhttpd.h b/src/uhttpd.h index aecec9a..d90cd7d 100644 --- a/src/uhttpd.h +++ b/src/uhttpd.h @@ -79,6 +79,11 @@ typedef void (*uh_path_handler_prototype)(struct uh_connection *conn, int event) struct uh_server { void (*free)(struct uh_server *srv); + /* + ** Start n worker processes to process the requests + ** If n is -1, automatically to available CPUs + */ + void (*start_worker)(struct uh_server *srv, int n); #if UHTTPD_SSL_SUPPORT int (*ssl_init)(struct uh_server *srv, const char *cert, const char *key); #endif