# HG changeset patch # User jbe # Date 1429032653 -7200 # Node ID 37532927dba9d0de7bc1c70c9c4e6d0eff753fc8 # Parent e0ab9fd00cb1a4e892584c09d58f590d08358497 Introduced new proto "main" to allow for a main thread diff -r e0ab9fd00cb1 -r 37532927dba9 helloworld.lua --- a/helloworld.lua Tue Apr 14 18:20:39 2015 +0200 +++ b/helloworld.lua Tue Apr 14 19:30:53 2015 +0200 @@ -6,6 +6,13 @@ local http = require "moonbridge_http" listen{ + { proto = "main" }, + connect = function() + print("Main function executed") + end +} + +listen{ { proto = "tcp", host = "127.0.0.1", port = 8080 }, -- IPv4 { proto = "tcp", host = "::1", port = 8080 }, -- IPv6 connect = http.generate_handler( diff -r e0ab9fd00cb1 -r 37532927dba9 moonbridge.c --- a/moonbridge.c Tue Apr 14 18:20:39 2015 +0200 +++ b/moonbridge.c Tue Apr 14 19:30:53 2015 +0200 @@ -123,9 +123,10 @@ #define MOONBR_PSTATE_FORKED 2 /* Enum for 'proto' field of struct moonbr_listener */ -#define MOONBR_PROTO_INTERVAL 1 -#define MOONBR_PROTO_LOCAL 2 -#define MOONBR_PROTO_TCP 3 +#define MOONBR_PROTO_MAIN 1 +#define MOONBR_PROTO_INTERVAL 2 +#define MOONBR_PROTO_LOCAL 3 +#define MOONBR_PROTO_TCP 4 /* Data structure for a pool's listener that can accept incoming connections */ struct moonbr_listener { @@ -167,6 +168,7 @@ struct moonbr_worker *next_worker; struct moonbr_worker *prev_idle_worker; struct moonbr_worker *next_idle_worker; + int main; /* nonzero = terminate Moonbridge when this worker dies */ int idle; /* nonzero = waiting for command from parent process */ int assigned; /* nonzero = currently handling a connection */ pid_t pid; @@ -513,6 +515,10 @@ for (i=0; ilistener_count; i++) { struct moonbr_listener *listener = &pool->listener[i]; switch (listener->proto) { + case MOONBR_PROTO_MAIN: + /* nothing to do here: starting main thread is performed in moonbr_run() function */ + moonbr_log(LOG_INFO, "Adding main thread"); + break; case MOONBR_PROTO_INTERVAL: /* nothing to do here: starting intervals is performed in moonbr_run() function */ if (!listener->type_specific.interval.name) { @@ -771,9 +777,17 @@ } if (controlmsg == MOONBR_COMMAND_TERMINATE) break; listener = moonbr_child_receive_pointer(MOONBR_FD_CONTROL); - if (listener->proto == MOONBR_PROTO_INTERVAL && fd >= 0) { + if ( + listener->proto != MOONBR_PROTO_LOCAL && + listener->proto != MOONBR_PROTO_TCP && + fd >= 0 + ) { moonbr_child_log_fatal("Received unexpected file descriptor from parent process"); - } else if (listener->proto != MOONBR_PROTO_INTERVAL && fd < 0) { + } else if ( + listener->proto != MOONBR_PROTO_MAIN && + listener->proto != MOONBR_PROTO_INTERVAL && + fd < 0 + ) { moonbr_child_log_fatal("Missing file descriptor from parent process"); } if (fd >= 0) moonbr_io_pushhandle(L, fd); @@ -1000,6 +1014,7 @@ MOONBR_DESTROY_IDLE_OR_ASSIGNED : MOONBR_DESTROY_PREPARE ); + //if (worker->main) moonbr_initiate_shutdown(); // TODO if (worker->prev_worker) worker->prev_worker->next_worker = worker->next_worker; else worker->pool->first_worker = worker->next_worker; if (worker->next_worker) worker->next_worker->prev_worker = worker->prev_worker; @@ -1396,7 +1411,15 @@ static void moonbr_connect(struct moonbr_pool *pool) { struct moonbr_listener *listener = moonbr_pop_connected_listener(pool); struct moonbr_worker *worker; - if (listener->proto == MOONBR_PROTO_INTERVAL) { + if (listener->proto == MOONBR_PROTO_MAIN) { + worker = moonbr_pop_idle_worker(pool); + if (moonbr_stat) { + moonbr_log(LOG_INFO, "Dispatching main thread of pool #%i to PID %i", listener->pool->poolnum, (int)worker->pid); + } + worker->main = 1; + moonbr_send_control_message(worker, MOONBR_COMMAND_CONNECT, -1, listener); + /* do not push listener to queue of idle listeners */ + } else if (listener->proto == MOONBR_PROTO_INTERVAL) { worker = moonbr_pop_idle_worker(pool); if (moonbr_stat) { moonbr_log(LOG_INFO, "Dispatching interval timer \"%s\" of pool #%i to PID %i", listener->type_specific.interval.name, listener->pool->poolnum, (int)worker->pid); @@ -1537,14 +1560,12 @@ moonbr_remove_idle_listener(listener); moonbr_add_connected_listener(listener); } - } else if (listener->proto == MOONBR_PROTO_INTERVAL) { - if (!timercmp(&listener->type_specific.interval.wakeup, &now, >)) { - moonbr_remove_idle_listener(listener); - moonbr_add_connected_listener(listener); - } - } else { - moonbr_log(LOG_CRIT, "Internal error (should not happen): Listener is neither an interval timer nor has the 'pollidx' value set"); - moonbr_terminate_error(); + } else if ( + listener->proto != MOONBR_PROTO_INTERVAL || + !timercmp(&listener->type_specific.interval.wakeup, &now, >) + ) { + moonbr_remove_idle_listener(listener); + moonbr_add_connected_listener(listener); } } /* process input from child processes */ @@ -1856,6 +1877,7 @@ struct moonbr_pool *pool; const char *proto; int i; + int dynamic = 0; /* nonzero = listeners exist which require dynamic worker creation */ pool = lua_touserdata(L, 1); for (i=0; ilistener_count; i++) { struct moonbr_listener *listener = &pool->listener[i]; @@ -1868,7 +1890,10 @@ #endif lua_getfield(L, 3, "proto"); proto = lua_tostring(L, -1); - if (proto && !strcmp(proto, "interval")) { + if (proto && !strcmp(proto, "main")) { + listener->proto = MOONBR_PROTO_MAIN; + } else if (proto && !strcmp(proto, "interval")) { + dynamic = 1; listener->proto = MOONBR_PROTO_INTERVAL; lua_getfield(L, 3, "name"); { @@ -1901,6 +1926,7 @@ sizeof(listener->type_specific.socket.addr.addr_un) - ((void *)listener->type_specific.socket.addr.addr_un.sun_path - (void *)&listener->type_specific.socket.addr.addr_un) ) - 1; /* one byte for termination */ + dynamic = 1; listener->proto = MOONBR_PROTO_LOCAL; lua_getfield(L, 3, "path"); path = lua_tostring(L, -1); @@ -1917,6 +1943,7 @@ struct addrinfo *res, *addrinfo; int errcode; const char *ip; + dynamic = 1; lua_getfield(L, 3, "host"); host = lua_isnil(L, -1) ? "::" : lua_tostring(L, -1); if (!host) { @@ -1995,23 +2022,29 @@ } } lua_settop(L, 2); - moonbr_listen_init_pool_forkoption("pre_fork", pre_fork, 1); - moonbr_listen_init_pool_forkoption("min_fork", min_fork, pool->pre_fork > 2 ? pool->pre_fork : 2); - moonbr_listen_init_pool_forkoption("max_fork", max_fork, pool->min_fork > 16 ? pool->min_fork : 16); - if (!moonbr_listen_init_pool_timeoption("fork_delay", fork_delay, 0, 250000)) { - luaL_error(L, "Option \"fork_delay\" is expected to be a non-negative number"); - } - if (!moonbr_listen_init_pool_timeoption("fork_error_delay", fork_error_delay, 2, 0)) { - luaL_error(L, "Option \"fork_error_delay\" is expected to be a non-negative number"); - } - if (!moonbr_listen_init_pool_timeoption("exit_delay", exit_delay, 60, 0)) { - luaL_error(L, "Option \"exit_delay\" is expected to be a non-negative number"); - } - if (timercmp(&pool->fork_error_delay, &pool->fork_delay, <)) { - pool->fork_error_delay = pool->fork_delay; - } - if (!moonbr_listen_init_pool_timeoption("idle_timeout", idle_timeout, 0, 0)) { - luaL_error(L, "Option \"idle_timeout\" is expected to be a non-negative number"); + if (dynamic) { + moonbr_listen_init_pool_forkoption("pre_fork", pre_fork, 1); + moonbr_listen_init_pool_forkoption("min_fork", min_fork, pool->pre_fork > 2 ? pool->pre_fork : 2); + moonbr_listen_init_pool_forkoption("max_fork", max_fork, pool->min_fork > 16 ? pool->min_fork : 16); + if (!moonbr_listen_init_pool_timeoption("fork_delay", fork_delay, 0, 250000)) { + luaL_error(L, "Option \"fork_delay\" is expected to be a non-negative number"); + } + if (!moonbr_listen_init_pool_timeoption("fork_error_delay", fork_error_delay, 2, 0)) { + luaL_error(L, "Option \"fork_error_delay\" is expected to be a non-negative number"); + } + if (!moonbr_listen_init_pool_timeoption("exit_delay", exit_delay, 60, 0)) { + luaL_error(L, "Option \"exit_delay\" is expected to be a non-negative number"); + } + if (timercmp(&pool->fork_error_delay, &pool->fork_delay, <)) { + pool->fork_error_delay = pool->fork_delay; + } + if (!moonbr_listen_init_pool_timeoption("idle_timeout", idle_timeout, 0, 0)) { + luaL_error(L, "Option \"idle_timeout\" is expected to be a non-negative number"); + } + } else { + pool->pre_fork = 0; + pool->min_fork = pool->listener_count; + pool->max_fork = pool->listener_count; } lua_getfield(L, 2, "memory_limit"); if (!lua_isnil(L, -1)) {