# HG changeset patch # User Tero Marttila # Date 1222370182 -10800 # Node ID 10b53719659c07ae56ef82cbe9d81d57e1896e54 # Parent 11757d6b43a6410f6d9394cac604262cd0a3ad1f signal handling diff -r 11757d6b43a6 -r 10b53719659c Makefile --- a/Makefile Thu Sep 25 21:28:08 2008 +0300 +++ b/Makefile Thu Sep 25 22:16:22 2008 +0300 @@ -12,7 +12,7 @@ BIN_NAMES = hello helloworld bin/helloworld: -bin/hello: obj/evfuse.o obj/lib/common.o +bin/hello: obj/evfuse.o obj/lib/common.o obj/lib/signals.o # computed LDFLAGS = ${LIBRARY_PATHS} ${LIBRARY_LIST} diff -r 11757d6b43a6 -r 10b53719659c src/evfuse.c --- a/src/evfuse.c Thu Sep 25 21:28:08 2008 +0300 +++ b/src/evfuse.c Thu Sep 25 22:16:22 2008 +0300 @@ -7,6 +7,9 @@ #include "lib/common.h" struct evfuse { + // our mountpoint + char *mountpoint; + // the /dev/fuse fd/channel that we get from fuse_mount struct fuse_chan *chan; @@ -61,7 +64,6 @@ struct evfuse *evfuse_new (struct event_base *evbase, struct fuse_args *args, struct fuse_lowlevel_ops *llops, void *cb_data) { struct evfuse *ctx = NULL; - char *mountpoint; int multithreaded, foreground; // allocate our context @@ -69,11 +71,11 @@ ERROR("calloc"); // parse the commandline for the mountpoint - if (fuse_parse_cmdline(args, &mountpoint, &multithreaded, &foreground) == -1) + if (fuse_parse_cmdline(args, &ctx->mountpoint, &multithreaded, &foreground) == -1) ERROR("fuse_parse_cmdline"); // mount it - if ((ctx->chan = fuse_mount(mountpoint, args)) == NULL) + if ((ctx->chan = fuse_mount(ctx->mountpoint, args)) == NULL) PERROR("fuse_mount_common"); // the receive buffer stufff @@ -106,3 +108,24 @@ return NULL; } + +void evfuse_close (struct evfuse *ctx) { + // remove our event + if (event_del(ctx->ev)) + PWARNING("event_del"); + + // remove the chan + fuse_session_remove_chan(ctx->chan); + + // destroy the session + fuse_session_destroy(ctx->session); + + // unmount + fuse_unmount(ctx->mountpoint, ctx->chan); + + // free + free(ctx->recv_buf); + free(ctx->mountpoint); + free(ctx); +} + diff -r 11757d6b43a6 -r 10b53719659c src/evfuse.h --- a/src/evfuse.h Thu Sep 25 21:28:08 2008 +0300 +++ b/src/evfuse.h Thu Sep 25 22:16:22 2008 +0300 @@ -16,4 +16,10 @@ */ struct evfuse *evfuse_new (struct event_base *evbase, struct fuse_args *args, struct fuse_lowlevel_ops *llops, void *cb_data); +/* + * Close a evfuse context. + */ +void evfuse_close (struct evfuse *ctx); + #endif /* EVFUSE_H */ + diff -r 11757d6b43a6 -r 10b53719659c src/hello.c --- a/src/hello.c Thu Sep 25 21:28:08 2008 +0300 +++ b/src/hello.c Thu Sep 25 22:16:22 2008 +0300 @@ -7,6 +7,7 @@ #include "lib/common.h" #include "lib/math.h" +#include "lib/signals.h" #include "evfuse.h" const char *file_name = "hello"; @@ -15,6 +16,8 @@ static struct hello { struct event_base *ev_base; + struct signals *signals; + struct evfuse *ev_fuse; } ctx; @@ -231,22 +234,41 @@ int main (int argc, char **argv) { struct fuse_args fuse_args = FUSE_ARGS_INIT(argc, argv); + + // zero + memset(&ctx, 0, sizeof(ctx)); // init libevent if ((ctx.ev_base = event_base_new()) == NULL) - FATAL("event_base_new"); + ERROR("event_base_new"); + // setup signals + if ((ctx.signals = signals_default(ctx.ev_base)) == NULL) + ERROR("signals_default"); + // open fuse if ((ctx.ev_fuse = evfuse_new(ctx.ev_base, &fuse_args, &hello_llops, &ctx)) == NULL) - FATAL("evfuse_new"); + ERROR("evfuse_new"); // run libevent INFO("running libevent loop"); if (event_base_dispatch(ctx.ev_base)) - PWARNING("event_base_dispatch"); + PERROR("event_base_dispatch"); + + // clean shutdown +error : // cleanup - event_base_free(ctx.ev_base); + if (ctx.ev_fuse) + evfuse_close(ctx.ev_fuse); + + if (ctx.signals) + signals_free(ctx.signals); + + if (ctx.ev_base) + event_base_free(ctx.ev_base); + + fuse_opt_free_args(&fuse_args); } diff -r 11757d6b43a6 -r 10b53719659c src/lib/signals.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/signals.c Thu Sep 25 22:16:22 2008 +0300 @@ -0,0 +1,109 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +#include "signals.h" +#include "common.h" + +struct signals { + struct event_base *ev_base; + + struct signal { + struct event *ev; + } sig_list[MAX_SIGNALS]; + + int sig_count; +}; + +void signals_loopexit (int signal, short event, void *arg) { + struct signals *signals = arg; + + INFO("[signal] caught %s: exiting the event loop", strsignal(signal)); + + if (event_base_loopexit(signals->ev_base, NULL)) + FATAL("event_base_loopexit"); +} + +void signals_ignore (int signal, short event, void *arg) { + struct signals *signals = arg; + + (void) signals; + + /* ignore */ +} + +struct signals *signals_alloc (struct event_base *ev_base) { + struct signals *signals = NULL; + + if ((signals = calloc(1, sizeof(*signals))) == NULL) + ERROR("calloc"); + + // simple attributes + signals->ev_base = ev_base; + + // done + return signals; + +error: + return NULL; +} + +int signals_add (struct signals *signals, int sigval, void (*sig_handler)(evutil_socket_t, short, void *)) { + struct signal *sig_info; + + // find our sig_info + assert(signals->sig_count < MAX_SIGNALS); + sig_info = &signals->sig_list[signals->sig_count++]; + + // set up the libevent signal events + if ((sig_info->ev = signal_new(signals->ev_base, sigval, sig_handler, signals)) == NULL) + PERROR("signal_new"); + + if (signal_add(sig_info->ev, NULL)) + PERROR("signal_add"); + + // success + return 0; + +error: + return -1; +} + +struct signals *signals_default (struct event_base *ev_base) { + struct signals *signals = NULL; + + // alloc signals + if ((signals = signals_alloc(ev_base)) == NULL) + return NULL; + + // add the set of default signals + if ( signals_add(signals, SIGPIPE, &signals_ignore) + || signals_add(signals, SIGINT, &signals_loopexit) + ) ERROR("signals_add"); + + // success + return signals; + +error: + if (signals) + signals_free(signals); + + return NULL; +} + +void signals_free (struct signals *signals) { + int i; + + // free all events + for (i = 0; i < signals->sig_count; i++) { + if (signal_del(signals->sig_list[i].ev)) + PWARNING("signal_del"); + + } + + // free the info itself + free(signals); +} + diff -r 11757d6b43a6 -r 10b53719659c src/lib/signals.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/signals.h Thu Sep 25 22:16:22 2008 +0300 @@ -0,0 +1,54 @@ +#ifndef LIB_SIGNAL_H +#define LIB_SIGNAL_H + +/* + * Handle signals in a libevent-sane way + */ + +#include + +/* + * How many signals we can define actions for + */ +#define MAX_SIGNALS 8 + +/* + * info about a set of signals + */ +struct signals; + +/* + * Used as a handler for signals that should cause a loopexit. + */ +void signals_loopexit (int signal, short event, void *arg); + +/* + * Used to receive signals, but discard them. + */ +void signals_ignore (int signal, short event, void *arg); + +/* + * Allocate a signals struct, acting on the given ev_base. + * + * Returns NULL on failure + */ +struct signals *signals_alloc (struct event_base *ev_base); + +/* + * Add a signal to be handled by the given signals struct with the given handler. + */ +int signals_add (struct signals *signals, int sigval, void (*sig_handler)(evutil_socket_t, short, void *)); + +/* + * Add a set of default signals + * SIGPIPE signals_ignore + * SIGINT signals_loopexit + */ +struct signals *signals_default (struct event_base *ev_base); + +/* + * Free the resources/handlers associated with the given signal handler + */ +void signals_free (struct signals *signals); + +#endif /* LIB_SIGNAL_H */