From 9308175caf833485c55854deeffd0e28137baf9a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 8 Nov 2009 17:17:33 +0000 Subject: [PATCH] misc. bugfixes and API improvements --- src/arm/arm_api.c | 24 +++- src/arm/gnunet-service-arm.c | 49 ++++++- src/arm/test_gnunet_arm.sh | 2 +- src/core/gnunet-service-core.c | 4 +- src/datastore/gnunet-service-datastore.c | 4 +- src/fs/gnunet-service-fs.c | 4 +- src/fs/test_fs_search_data.conf | 2 +- src/include/gnunet_service_lib.h | 20 +++ src/peerinfo/gnunet-service-peerinfo.c | 4 +- src/statistics/gnunet-service-statistics.c | 4 +- src/template/gnunet-service-template.c | 4 +- src/testing/test_testing_connect.c | 4 +- src/testing/test_testing_connect_peer1.conf | 2 + src/testing/test_testing_connect_peer2.conf | 2 + src/testing/testing.c | 23 +-- src/topology/test_gnunet_service_topology.c | 3 +- src/transport/gnunet-service-transport.c | 1 + src/util/client.c | 29 +++- src/util/connection.c | 3 + src/util/gnunet-service-resolver.c | 3 +- src/util/scheduler.c | 14 +- src/util/server.c | 152 ++++++++------------ src/util/service.c | 21 ++- src/util/test_container_heap.c | 19 +-- src/util/test_server_disconnect.c | 5 +- src/util/test_server_with_client.c | 15 +- src/util/test_service.c | 3 + 27 files changed, 268 insertions(+), 152 deletions(-) diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c index f2d2b293a..bc80b779f 100644 --- a/src/arm/arm_api.c +++ b/src/arm/arm_api.c @@ -163,12 +163,22 @@ arm_service_report (void *cls, if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { +#if DEBUG_ARM + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Looks like `%s' is already running.\n", + "gnunet-service-arm"); +#endif /* arm is running! */ if (pos->callback != NULL) pos->callback (pos->cls, GNUNET_YES); GNUNET_free (pos); return; } +#if DEBUG_ARM + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Looks like `%s' is not running, will start it.\n", + "gnunet-service-arm"); +#endif /* FIXME: should we check that HOSTNAME for 'arm' is localhost? */ /* start service */ if (GNUNET_OK != @@ -236,7 +246,10 @@ handle_response (void *cls, const struct GNUNET_MessageHeader *msg) if (msg == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Error receiving response from ARM service\n")); + _("Error receiving response to `%s' request from ARM service\n"), + (sc->type == GNUNET_MESSAGE_TYPE_ARM_START) + ? "START" + : "STOP"); GNUNET_CLIENT_disconnect (sc->h->client); sc->h->client = GNUNET_CLIENT_connect (sc->h->sched, "arm", @@ -304,7 +317,10 @@ change_service (struct GNUNET_ARM_Handle *h, } #if DEBUG_ARM GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("ARM requests starting of service `%s'.\n"), service_name); + (type == GNUNET_MESSAGE_TYPE_ARM_START) + ? _("Requesting start of service `%s'.\n") + : _("Requesting termination of service `%s'.\n"), + service_name); #endif sctx = GNUNET_malloc (sizeof (struct RequestContext) + slen); sctx->h = h; @@ -355,7 +371,7 @@ GNUNET_ARM_start_service (struct GNUNET_ARM_Handle *h, GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"), service_name); - if (0 == strcmp ("arm", service_name)) + if (0 == strcasecmp ("arm", service_name)) { sctx = GNUNET_malloc (sizeof (struct RequestContext)); sctx->h = h; @@ -388,7 +404,7 @@ GNUNET_ARM_stop_service (struct GNUNET_ARM_Handle *h, { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stopping service `%s'\n"), service_name); - if (0 == strcmp ("arm", service_name)) + if (0 == strcasecmp ("arm", service_name)) { GNUNET_CLIENT_service_shutdown (h->client); h->client = NULL; diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c index f907d944f..4a30848eb 100644 --- a/src/arm/gnunet-service-arm.c +++ b/src/arm/gnunet-service-arm.c @@ -157,6 +157,17 @@ static char *prefix_command; */ static int in_shutdown; +/** + * Handle to our server instance. Our server is a bit special in that + * its service is not immediately stopped once we get a shutdown + * request (since we need to continue service until all of our child + * processes are dead). This handle is used to shut down the server + * (and thus trigger process termination) once all child processes are + * also dead. A special option in the ARM configuration modifies the + * behaviour of the service implementation to not do the shutdown + * immediately. + */ +static struct GNUNET_SERVER_Handle *server; /** * Background task doing maintenance. @@ -646,9 +657,16 @@ maint (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) pos = running; while (NULL != pos) { - if ( (pos->pid != 0) && - (0 != PLIBC_KILL (pos->pid, SIGTERM)) ) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + if (pos->pid != 0) + { +#if DEBUG_ARM + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending SIGTERM to `%s'\n", + pos->name); +#endif + if (0 != PLIBC_KILL (pos->pid, SIGTERM)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + } pos = pos->next; } } @@ -656,7 +674,14 @@ maint (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if ( (in_shutdown == GNUNET_YES) && (running == NULL) ) - return; /* we are done! */ + { +#if DEBUG_ARM + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "ARM service terminates.\n"); +#endif + GNUNET_SERVER_destroy (server); + return; /* we are done! */ + } GNUNET_SCHEDULER_add_delayed (tc->sched, (in_shutdown == GNUNET_YES) ? MAINT_FAST_FREQUENCY @@ -716,6 +741,12 @@ maint (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Service `%s' terminated with status %s/%d, will try to restart it!\n"), pos->name, statstr, statcode); +#if DEBUG_ARM + else + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Service `%s' terminated with status %s/%d\n", + pos->name, statstr, statcode); +#endif /* schedule restart */ pos->pid = 0; prev = pos; @@ -762,20 +793,22 @@ static struct GNUNET_SERVER_MessageHandler handlers[] = { * * @param cls closure * @param s scheduler to use - * @param server the initialized server + * @param serv the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SCHEDULER_Handle *s, - struct GNUNET_SERVER_Handle *server, + struct GNUNET_SERVER_Handle *serv, const struct GNUNET_CONFIGURATION_Handle *c) { char *defaultservices; char *pos; + GNUNET_assert (serv != NULL); cfg = c; sched = s; + server = serv; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", @@ -831,7 +864,9 @@ main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, - argv, "arm", &run, NULL)) ? 0 : 1; + argv, "arm", + GNUNET_YES, + &run, NULL)) ? 0 : 1; } /* end of gnunet-service-arm.c */ diff --git a/src/arm/test_gnunet_arm.sh b/src/arm/test_gnunet_arm.sh index d36c2ca38..4c3edb249 100755 --- a/src/arm/test_gnunet_arm.sh +++ b/src/arm/test_gnunet_arm.sh @@ -1,6 +1,6 @@ #!/bin/sh -exe="./gnunet-arm -c test_arm_api_data.conf" +exe="valgrind --trace-children=yes ./gnunet-arm -c test_arm_api_data.conf" out=`mktemp /tmp/test-gnunet-arm-logXXXXXXXX` #DEBUG="-L DEBUG" diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c index 839eb2727..9d9ba5690 100644 --- a/src/core/gnunet-service-core.c +++ b/src/core/gnunet-service-core.c @@ -3214,7 +3214,9 @@ main (int argc, char *const *argv) return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, - "core", &run, NULL)) ? 0 : 1; + "core", + GNUNET_SERVICE_OPTION_NONE, + &run, NULL)) ? 0 : 1; } /* end of gnunet-service-core.c */ diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c index 27b1cd58e..d58f0f8d9 100644 --- a/src/datastore/gnunet-service-datastore.c +++ b/src/datastore/gnunet-service-datastore.c @@ -1341,7 +1341,9 @@ main (int argc, char *const *argv) ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, - "datastore", &run, NULL)) ? 0 : 1; + "datastore", + GNUNET_SERVICE_OPTION_NONE, + &run, NULL)) ? 0 : 1; return ret; } diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c index 0e592e094..bec69f6ec 100644 --- a/src/fs/gnunet-service-fs.c +++ b/src/fs/gnunet-service-fs.c @@ -3358,7 +3358,9 @@ main (int argc, char *const *argv) return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, - "fs", &run, NULL)) ? 0 : 1; + "fs", + GNUNET_SERVICE_OPTION_NONE, + &run, NULL)) ? 0 : 1; } /* end of gnunet-service-fs.c */ diff --git a/src/fs/test_fs_search_data.conf b/src/fs/test_fs_search_data.conf index fd82a15fc..cffe83f57 100644 --- a/src/fs/test_fs_search_data.conf +++ b/src/fs/test_fs_search_data.conf @@ -1,6 +1,6 @@ [PATHS] SERVICEHOME = /tmp/gnunet-test-fs-search/ -DEFAULTCONFIG = test_fs_download_data.conf +DEFAULTCONFIG = test_fs_search_data.conf [gnunetd] HOSTKEY = $SERVICEHOME/.hostkey diff --git a/src/include/gnunet_service_lib.h b/src/include/gnunet_service_lib.h index 82089954e..66e4f0cd9 100644 --- a/src/include/gnunet_service_lib.h +++ b/src/include/gnunet_service_lib.h @@ -54,6 +54,24 @@ typedef void (*GNUNET_SERVICE_Main) (void *cls, cfg); +/** + * Options for the service (bitmask). + */ +enum GNUNET_SERVICE_Options + { + /** + * Use defaults. + */ + GNUNET_SERVICE_OPTION_NONE = 0, + + /** + * Do not trigger server shutdown on signals, allow for the user + * to terminate the server explicitly when needed. + */ + GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN = 1 + }; + + /** * Run a standard GNUnet service startup sequence (initialize loggers * and configuration, parse options). @@ -61,6 +79,7 @@ typedef void (*GNUNET_SERVICE_Main) (void *cls, * @param argc number of command line arguments * @param argv command line arguments * @param serviceName our service name + * @param opt service options * @param task main task of the service * @param task_cls closure for task * @return GNUNET_SYSERR on error, GNUNET_OK @@ -69,6 +88,7 @@ typedef void (*GNUNET_SERVICE_Main) (void *cls, int GNUNET_SERVICE_run (int argc, char *const *argv, const char *serviceName, + enum GNUNET_SERVICE_Options opt, GNUNET_SERVICE_Main task, void *task_cls); diff --git a/src/peerinfo/gnunet-service-peerinfo.c b/src/peerinfo/gnunet-service-peerinfo.c index f5a60470e..ee1287831 100644 --- a/src/peerinfo/gnunet-service-peerinfo.c +++ b/src/peerinfo/gnunet-service-peerinfo.c @@ -711,7 +711,9 @@ main (int argc, char *const *argv) ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, - "peerinfo", &run, NULL)) ? 0 : 1; + "peerinfo", + GNUNET_SERVICE_OPTION_NONE, + &run, NULL)) ? 0 : 1; GNUNET_free_non_null (networkIdDirectory); GNUNET_free_non_null (trustDirectory); return ret; diff --git a/src/statistics/gnunet-service-statistics.c b/src/statistics/gnunet-service-statistics.c index 8de9a8047..c90038e03 100644 --- a/src/statistics/gnunet-service-statistics.c +++ b/src/statistics/gnunet-service-statistics.c @@ -486,7 +486,9 @@ main (int argc, char *const *argv) return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, - "statistics", &run, NULL)) ? 0 : 1; + "statistics", + GNUNET_SERVICE_OPTION_NONE, + &run, NULL)) ? 0 : 1; } /* end of gnunet-service-statistics.c */ diff --git a/src/template/gnunet-service-template.c b/src/template/gnunet-service-template.c index 15ba94b7d..39d332226 100644 --- a/src/template/gnunet-service-template.c +++ b/src/template/gnunet-service-template.c @@ -88,7 +88,9 @@ main (int argc, char *const *argv) return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, - "template", &run, NULL)) ? 0 : 1; + "template", + GNUNET_SERVICE_OPTION_NONE, + &run, NULL)) ? 0 : 1; } /* end of gnunet-service-template.c */ diff --git a/src/testing/test_testing_connect.c b/src/testing/test_testing_connect.c index 431b63963..ade3fed11 100644 --- a/src/testing/test_testing_connect.c +++ b/src/testing/test_testing_connect.c @@ -24,7 +24,7 @@ #include "platform.h" #include "gnunet_testing_lib.h" -#define VERBOSE GNUNET_NO +#define VERBOSE GNUNET_YES /** @@ -51,7 +51,7 @@ static void end2_cb(void *cls, GNUNET_assert (emsg == NULL); #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Daemon terminated, will now exit.\n"); + "Both daemons terminated, will now exit.\n"); #endif ok = 0; } diff --git a/src/testing/test_testing_connect_peer1.conf b/src/testing/test_testing_connect_peer1.conf index 020504728..32ddbfc4d 100644 --- a/src/testing/test_testing_connect_peer1.conf +++ b/src/testing/test_testing_connect_peer1.conf @@ -17,6 +17,7 @@ PLUGINS = tcp PORT = 12566 HOSTNAME = localhost DEFAULTSERVICES = peerinfo transport core +DEBUG = YES [statistics] PORT = 12567 @@ -32,6 +33,7 @@ HOSTNAME = localhost [core] PORT = 12570 HOSTNAME = localhost +DEBUG = YES [testing] WEAKRANDOM = YES diff --git a/src/testing/test_testing_connect_peer2.conf b/src/testing/test_testing_connect_peer2.conf index 196e96a84..a152ff237 100644 --- a/src/testing/test_testing_connect_peer2.conf +++ b/src/testing/test_testing_connect_peer2.conf @@ -17,6 +17,7 @@ PLUGINS = tcp PORT = 22566 DEFAULTSERVICES = peerinfo transport core HOSTNAME = localhost +DEBUG = YES [statistics] PORT = 22567 @@ -32,6 +33,7 @@ HOSTNAME = localhost [core] PORT = 22570 HOSTNAME = localhost +DEBUG = YES [testing] WEAKRANDOM = YES diff --git a/src/testing/testing.c b/src/testing/testing.c index e34e7a9ac..6edefb14a 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c @@ -40,13 +40,13 @@ #include "gnunet_testing_lib.h" #include "gnunet_transport_service.h" -#define DEBUG_TESTING GNUNET_NO +#define DEBUG_TESTING GNUNET_YES /** * How long do we wait after starting gnunet-service-arm * for the core service to be alive? */ -#define ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) +#define ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * How many times are we willing to try to wait for "scp" or @@ -236,6 +236,7 @@ testing_init (void *cls, d->cb = NULL; if (server == NULL) { + d->server = NULL; if (GNUNET_YES == d->dead) GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls); else if (NULL != cb) @@ -428,15 +429,15 @@ start_fsm (void *cls, "gnunet-service-arm"); #endif d->phase = SP_START_CORE; - GNUNET_CORE_connect (d->sched, - d->cfg, - ARM_START_WAIT, - d, - &testing_init, - NULL, NULL, NULL, - NULL, GNUNET_NO, - NULL, GNUNET_NO, - no_handlers); + d->server = GNUNET_CORE_connect (d->sched, + d->cfg, + ARM_START_WAIT, + d, + &testing_init, + NULL, NULL, NULL, + NULL, GNUNET_NO, + NULL, GNUNET_NO, + no_handlers); break; case SP_START_CORE: GNUNET_break (0); diff --git a/src/topology/test_gnunet_service_topology.c b/src/topology/test_gnunet_service_topology.c index 2536f5454..130f40629 100644 --- a/src/topology/test_gnunet_service_topology.c +++ b/src/topology/test_gnunet_service_topology.c @@ -66,7 +66,8 @@ notify_connect_complete(void *cls, { /* FIXME: check that topology adds a few more links in addition to those that were seeded */ - sleep (100); + /* For now, sleep so we can have the daemon do some work */ + sleep (10); GNUNET_TESTING_daemons_stop (pg); ok = 0; } diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index efe53e021..5c5c64dbc 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -2709,6 +2709,7 @@ main (int argc, char *const *argv) GNUNET_SERVICE_run (argc, argv, "transport", + GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } diff --git a/src/util/client.c b/src/util/client.c index 05f579b9f..664b06271 100644 --- a/src/util/client.c +++ b/src/util/client.c @@ -566,7 +566,9 @@ write_test (void *cls, size_t size, void *buf) return 0; /* client disconnected */ } #if DEBUG_CLIENT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Transmitting TEST request.\n")); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmitting `%s' request.\n", + "TEST"); #endif msg = (struct GNUNET_MessageHeader *) buf; msg->type = htons (GNUNET_MESSAGE_TYPE_TEST); @@ -642,7 +644,6 @@ GNUNET_CLIENT_service_test (struct GNUNET_SCHEDULER_Handle *sched, static size_t client_notify (void *cls, size_t size, void *buf); - /** * This task is run if we should re-try connection to the * service after a while. @@ -657,6 +658,16 @@ client_delayed_retry (void *cls, struct GNUNET_CLIENT_TransmitHandle *th = cls; th->task = GNUNET_SCHEDULER_NO_TASK; + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + { +#if DEBUG_CLIENT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmission failed due to shutdown.\n"); +#endif + th->notify (th->notify_cls, 0, NULL); + GNUNET_free (th); + return; + } th->th = GNUNET_CONNECTION_notify_transmit_ready (th->sock->sock, th->size, GNUNET_TIME_absolute_get_remaining @@ -693,11 +704,19 @@ client_notify (void *cls, size_t size, void *buf) th->sock->th = NULL; if (buf == NULL) { + // FIXME: need a way to check if the + // reason is SHUTDOWN (not timeout) and + // if so NOT retry! delay = GNUNET_TIME_absolute_get_remaining (th->timeout); delay.value /= 2; if ((GNUNET_YES != th->auto_retry) || (0 == --th->attempts_left) || (delay.value < 1)) { +#if DEBUG_CLIENT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmission failed %u times, giving up.\n", + MAX_ATTEMPTS - th->attempts_left); +#endif GNUNET_break (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); return 0; @@ -708,6 +727,12 @@ client_notify (void *cls, size_t size, void *buf) th->sock->service_name, th->sock->cfg); GNUNET_assert (NULL != th->sock->sock); delay = GNUNET_TIME_relative_min (delay, GNUNET_TIME_UNIT_SECONDS); +#if DEBUG_CLIENT + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmission failed %u times, trying again in %llums.\n", + MAX_ATTEMPTS - th->attempts_left, + (unsigned long long) delay.value); +#endif th->task = GNUNET_SCHEDULER_add_delayed (th->sock->sched, delay, &client_delayed_retry, th); diff --git a/src/util/connection.c b/src/util/connection.c index 9bf2aa975..f88a7b5f2 100644 --- a/src/util/connection.c +++ b/src/util/connection.c @@ -1343,6 +1343,9 @@ transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /* no data ready for writing, terminate write loop */ return; } + GNUNET_assert (have <= sock->write_buffer_size); + GNUNET_assert (have + sock->write_buffer_pos <= sock->write_buffer_size); + GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_size); RETRY: ret = GNUNET_NETWORK_socket_send (sock->sock, &sock->write_buffer[sock-> diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c index 4dcabface..70f9128cc 100644 --- a/src/util/gnunet-service-resolver.c +++ b/src/util/gnunet-service-resolver.c @@ -516,7 +516,8 @@ main (int argc, char *const *argv) ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, - "resolver", &run, NULL)) ? 0 : 1; + "resolver", GNUNET_SERVICE_OPTION_NONE, + &run, NULL)) ? 0 : 1; while (head != NULL) { diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 16f65b457..dc428e592 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -560,6 +560,13 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) timeout = GNUNET_TIME_UNIT_ZERO; } ret = GNUNET_NETWORK_socket_select (rs, ws, NULL, timeout); + if (ret == GNUNET_SYSERR) + { + if (errno == EINTR) + continue; + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select"); + break; + } #ifndef MINGW if (GNUNET_NETWORK_fdset_handle_isset (rs, pr)) { @@ -584,13 +591,6 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) _("Looks like we're busy waiting...\n")); sleep (1); /* mitigate */ } - if (ret == GNUNET_SYSERR) - { - if (errno == EINTR) - continue; - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select"); - break; - } check_ready (&sched, rs, ws); run_ready (&sched); } diff --git a/src/util/server.c b/src/util/server.c index ff9c8c192..af26d278c 100644 --- a/src/util/server.c +++ b/src/util/server.c @@ -122,11 +122,6 @@ struct GNUNET_SERVER_Handle */ size_t maxbuf; - /** - * Pipe used to signal shutdown of the server. - */ - struct GNUNET_DISK_PipeHandle *shutpipe; - /** * Socket used to listen for new connections. Set to * "-1" by GNUNET_SERVER_destroy to initiate shutdown. @@ -134,9 +129,9 @@ struct GNUNET_SERVER_Handle struct GNUNET_NETWORK_Handle *listen_socket; /** - * Set to GNUNET_YES if we are shutting down. + * Task scheduled to do the listening. */ - int do_shutdown; + GNUNET_SCHEDULER_TaskIdentifier listen_task; /** * Do we ignore messages of types that we do not @@ -261,42 +256,6 @@ struct GNUNET_SERVER_Client }; -/** - * Server has been asked to shutdown, free resources. - */ -static void -destroy_server (struct GNUNET_SERVER_Handle *server) -{ - struct GNUNET_SERVER_Client *pos; - struct HandlerList *hpos; - struct NotifyList *npos; - -#if DEBUG_SERVER - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server shutting down.\n"); -#endif - GNUNET_assert (server->listen_socket == NULL); - if (GNUNET_OK != GNUNET_DISK_pipe_close (server->shutpipe)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "pipe-close"); - while (server->clients != NULL) - { - pos = server->clients; - server->clients = pos->next; - pos->server = NULL; - } - while (NULL != (hpos = server->handlers)) - { - server->handlers = hpos->next; - GNUNET_free (hpos); - } - while (NULL != (npos = server->disconnect_notify_list)) - { - server->disconnect_notify_list = npos->next; - GNUNET_free (npos); - } - GNUNET_free (server); -} - - /** * Scheduler says our listen socket is ready. * Process it! @@ -309,26 +268,23 @@ process_listen_socket (void *cls, struct GNUNET_CONNECTION_Handle *sock; struct GNUNET_SERVER_Client *client; struct GNUNET_NETWORK_FDSet *r; - const struct GNUNET_DISK_FileHandle *shutpipe; - if ((server->do_shutdown) || - ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)) + server->listen_task = GNUNET_SCHEDULER_NO_TASK; + r = GNUNET_NETWORK_fdset_create (); + GNUNET_NETWORK_fdset_set (r, server->listen_socket); + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { - /* shutdown was initiated */ - GNUNET_assert (server->listen_socket != NULL); - GNUNET_break (GNUNET_OK == - GNUNET_NETWORK_socket_close (server->listen_socket)); - server->listen_socket = NULL; - if (server->do_shutdown) - destroy_server (server); - return; + server->listen_task = GNUNET_SCHEDULER_add_select (server->sched, + GNUNET_SCHEDULER_PRIORITY_HIGH, + GNUNET_SCHEDULER_NO_TASK, + GNUNET_TIME_UNIT_FOREVER_REL, + r, NULL, &process_listen_socket, + server); + GNUNET_NETWORK_fdset_destroy (r); + return; /* ignore shutdown, someone else will take care of it! */ } - shutpipe = GNUNET_DISK_pipe_handle (server->shutpipe, - GNUNET_DISK_PIPE_END_READ); GNUNET_assert (GNUNET_NETWORK_fdset_isset - (tc->read_ready, server->listen_socket)); - GNUNET_assert (!GNUNET_NETWORK_fdset_handle_isset - (tc->read_ready, shutpipe)); + (tc->read_ready, server->listen_socket)); sock = GNUNET_CONNECTION_create_from_accept (tc->sched, server->access, server->access_cls, @@ -345,14 +301,11 @@ process_listen_socket (void *cls, GNUNET_SERVER_client_drop (client); } /* listen for more! */ - r = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_set (r, server->listen_socket); - GNUNET_NETWORK_fdset_handle_set (r, shutpipe); - GNUNET_SCHEDULER_add_select (server->sched, - GNUNET_SCHEDULER_PRIORITY_HIGH, - GNUNET_SCHEDULER_NO_TASK, - GNUNET_TIME_UNIT_FOREVER_REL, - r, NULL, &process_listen_socket, server); + server->listen_task = GNUNET_SCHEDULER_add_select (server->sched, + GNUNET_SCHEDULER_PRIORITY_HIGH, + GNUNET_SCHEDULER_NO_TASK, + GNUNET_TIME_UNIT_FOREVER_REL, + r, NULL, &process_listen_socket, server); GNUNET_NETWORK_fdset_destroy (r); } @@ -454,12 +407,6 @@ GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched, return NULL; } ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_Handle)); - if (NULL == (ret->shutpipe = GNUNET_DISK_pipe (GNUNET_NO))) - { - GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (lsock)); - GNUNET_free (ret); - return NULL; - } ret->sched = sched; ret->maxbuf = maxbuf; ret->idle_timeout = idle_timeout; @@ -471,14 +418,11 @@ GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched, { r = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_set (r, ret->listen_socket); - GNUNET_NETWORK_fdset_handle_set (r, - GNUNET_DISK_pipe_handle (ret->shutpipe, - GNUNET_DISK_PIPE_END_READ)); - GNUNET_SCHEDULER_add_select (sched, - GNUNET_SCHEDULER_PRIORITY_HIGH, - GNUNET_SCHEDULER_NO_TASK, - GNUNET_TIME_UNIT_FOREVER_REL, r, NULL, - &process_listen_socket, ret); + ret->listen_task = GNUNET_SCHEDULER_add_select (sched, + GNUNET_SCHEDULER_PRIORITY_HIGH, + GNUNET_SCHEDULER_NO_TASK, + GNUNET_TIME_UNIT_FOREVER_REL, r, NULL, + &process_listen_socket, ret); GNUNET_NETWORK_fdset_destroy (r); } return ret; @@ -491,18 +435,40 @@ GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched, void GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s) { - static char c; - - GNUNET_assert (s->do_shutdown == GNUNET_NO); - s->do_shutdown = GNUNET_YES; - if (s->listen_socket == NULL) - destroy_server (s); - else - GNUNET_break (1 == - GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle - (s->shutpipe, - GNUNET_DISK_PIPE_END_WRITE), &c, - sizeof (c))); + struct GNUNET_SERVER_Client *pos; + struct HandlerList *hpos; + struct NotifyList *npos; + +#if DEBUG_SERVER + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server shutting down.\n"); +#endif + if (GNUNET_SCHEDULER_NO_TASK != s->listen_task) + { + GNUNET_SCHEDULER_cancel (s->sched, + s->listen_task); + s->listen_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_close (s->listen_socket)); + s->listen_socket = NULL; + while (s->clients != NULL) + { + pos = s->clients; + s->clients = pos->next; + pos->server = NULL; + } + while (NULL != (hpos = s->handlers)) + { + s->handlers = hpos->next; + GNUNET_free (hpos); + } + while (NULL != (npos = s->disconnect_notify_list)) + { + s->disconnect_notify_list = npos->next; + GNUNET_free (npos); + } + GNUNET_free (s); + } diff --git a/src/util/service.c b/src/util/service.c index 173c0f566..60da8788f 100644 --- a/src/util/service.c +++ b/src/util/service.c @@ -513,6 +513,11 @@ struct GNUNET_SERVICE_Context */ int allow_shutdown; + /** + * Our options. + */ + enum GNUNET_SERVICE_Options options; + /** * Length of addr. */ @@ -1108,10 +1113,15 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) sctx->ret = GNUNET_SYSERR; return; } - GNUNET_SCHEDULER_add_delayed (tc->sched, - GNUNET_TIME_UNIT_FOREVER_REL, - &shutdown_task, - sctx->server); + if (0 == (sctx->options & GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN)) + { + /* install a task that will kill the server + process if the scheduler ever gets a shutdown signal */ + GNUNET_SCHEDULER_add_delayed (tc->sched, + GNUNET_TIME_UNIT_FOREVER_REL, + &shutdown_task, + sctx->server); + } sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers)); memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers)); i = 0; @@ -1277,6 +1287,7 @@ pid_file_delete (struct GNUNET_SERVICE_Context *sctx) * @param argc number of command line arguments * @param argv command line arguments * @param serviceName our service name + * @param opt service options * @param task main task of the service * @param task_cls closure for task * @return GNUNET_SYSERR on error, GNUNET_OK @@ -1286,6 +1297,7 @@ int GNUNET_SERVICE_run (int argc, char *const *argv, const char *serviceName, + enum GNUNET_SERVICE_Options opt, GNUNET_SERVICE_Main task, void *task_cls) { @@ -1311,6 +1323,7 @@ GNUNET_SERVICE_run (int argc, loglev = GNUNET_strdup ("WARNING"); cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_DAEMON_CONFIG_FILE); memset (&sctx, 0, sizeof (sctx)); + sctx.options = opt; sctx.ready_confirm_fd = -1; sctx.ret = GNUNET_OK; sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL; diff --git a/src/util/test_container_heap.c b/src/util/test_container_heap.c index 9e6a29ea4..7a23855c5 100644 --- a/src/util/test_container_heap.c +++ b/src/util/test_container_heap.c @@ -45,6 +45,7 @@ iterator_callback (void *cls, void *element, GNUNET_CONTAINER_HeapCost cost) return GNUNET_OK; } + int main (int argc, char **argv) { @@ -68,23 +69,23 @@ main (int argc, char **argv) neighbor6.cost = 30; GNUNET_CONTAINER_heap_insert (myHeap, &neighbor1, neighbor1.cost); - GNUNET_CONTAINER_heap_iterate (myHeap, iterator_callback, NULL); + GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_CONTAINER_heap_insert (myHeap, &neighbor2, neighbor2.cost); - GNUNET_CONTAINER_heap_iterate (myHeap, iterator_callback, NULL); + GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_CONTAINER_heap_insert (myHeap, &neighbor3, neighbor3.cost); - GNUNET_CONTAINER_heap_iterate (myHeap, iterator_callback, NULL); + GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_CONTAINER_heap_insert (myHeap, &neighbor4, neighbor4.cost); - GNUNET_CONTAINER_heap_iterate (myHeap, iterator_callback, NULL); + GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_CONTAINER_heap_insert (myHeap, &neighbor5, neighbor5.cost); - GNUNET_CONTAINER_heap_iterate (myHeap, iterator_callback, NULL); + GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_CONTAINER_heap_insert (myHeap, &neighbor6, neighbor6.cost); - GNUNET_CONTAINER_heap_iterate (myHeap, iterator_callback, NULL); + GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_CONTAINER_heap_remove_node (myHeap, &neighbor5); - GNUNET_CONTAINER_heap_iterate (myHeap, iterator_callback, NULL); + GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_CONTAINER_heap_remove_root (myHeap); - GNUNET_CONTAINER_heap_iterate (myHeap, iterator_callback, NULL); + GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_CONTAINER_heap_update_cost (myHeap, &neighbor6, 200); - GNUNET_CONTAINER_heap_iterate (myHeap, iterator_callback, NULL); + GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_CONTAINER_heap_destroy (myHeap); return 0; diff --git a/src/util/test_server_disconnect.c b/src/util/test_server_disconnect.c index 30fc34b08..7b35647ea 100644 --- a/src/util/test_server_disconnect.c +++ b/src/util/test_server_disconnect.c @@ -120,8 +120,11 @@ disconnect_notify (void *cls, const struct GNUNET_MessageHeader *msg) GNUNET_assert (ok == 7); ok = 0; GNUNET_CLIENT_disconnect (client); - GNUNET_SCHEDULER_shutdown (sched); + client = NULL; + GNUNET_SERVER_destroy (server); + server = NULL; GNUNET_CONFIGURATION_destroy (cfg); + cfg = NULL; } diff --git a/src/util/test_server_with_client.c b/src/util/test_server_with_client.c index 860ed3837..52b0addfa 100644 --- a/src/util/test_server_with_client.c +++ b/src/util/test_server_with_client.c @@ -103,6 +103,16 @@ recv_cb (void *cls, } +static void +clean_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + GNUNET_SERVER_destroy (server); + server = NULL; + GNUNET_CONFIGURATION_destroy (cfg); + cfg = NULL; +} + + /** * Functions with this signature are called whenever a client * is disconnected on the network level. @@ -115,8 +125,9 @@ notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { GNUNET_assert (ok == 5); ok = 0; - GNUNET_SCHEDULER_shutdown (sched); - GNUNET_CONFIGURATION_destroy (cfg); + GNUNET_SCHEDULER_add_delayed (sched, + GNUNET_TIME_UNIT_ZERO, + &clean_up, NULL); } diff --git a/src/util/test_service.c b/src/util/test_service.c index fa35da6e9..ab7011526 100644 --- a/src/util/test_service.c +++ b/src/util/test_service.c @@ -152,6 +152,7 @@ check () GNUNET_SERVICE_run (5, argv, "test_service", + GNUNET_SERVICE_OPTION_NONE, &runner, &ok)); GNUNET_assert (0 == ok); return ok; @@ -213,6 +214,7 @@ check6 () GNUNET_SERVICE_run (5, argv, "test_service6", + GNUNET_SERVICE_OPTION_NONE, &runner6, &ok)); GNUNET_assert (0 == ok); return ok; @@ -245,6 +247,7 @@ check6d () GNUNET_SERVICE_run (6, argv, "test_service6", + GNUNET_SERVICE_OPTION_NONE, &runner6, &ok)); GNUNET_break (0 == ok); return ok; -- 2.25.1