replace old SIGINT handling with SIGTERM, and have SIGINT just abort the console input line. Now EOF (^D) will cause lua_console to nexus_shutdown
authorTero Marttila <terom@fixme.fi>
Mon, 04 May 2009 23:19:50 +0300
changeset 170 1b2f28e26eef
parent 169 e6a1ce44aecc
child 171 b54f393c3df0
replace old SIGINT handling with SIGTERM, and have SIGINT just abort the console input line. Now EOF (^D) will cause lua_console to nexus_shutdown
src/console.c
src/console.h
src/lua_console.c
src/nexus.c
--- a/src/console.c	Mon May 04 20:55:43 2009 +0300
+++ b/src/console.c	Mon May 04 23:19:50 2009 +0300
@@ -7,6 +7,7 @@
 #include <readline/readline.h>
 #include <readline/history.h>
 
+#include <signal.h>
 #include <assert.h>
 
 /** The global console state */
@@ -35,9 +36,19 @@
 static void console_line (char *line)
 {
     struct console *console = &_console;
+    
+    // special-case EOF
+    if (!line) {
+        // prettify
+        rl_crlf();
+        rl_on_new_line();
 
-    // XXX: line == NULL -> EOF?
-    
+        if (console->callbacks->on_eof)
+            console->callbacks->on_eof(console->cb_arg);
+        
+        return;
+    }
+
     // update state
     console->have_input = false;
 
@@ -55,6 +66,20 @@
     console->have_input = true;
 }
 
+static void on_sigint (int sig)
+{
+    struct console *console = &_console;
+
+    (void) sig;
+
+    // interrupt the input line
+    rl_free_line_state();
+
+    // redisplay on new line
+    rl_crlf();
+    rl_callback_handler_install(console->config.prompt, console_line);
+}
+
 err_t console_init (struct console **console_ptr, struct event_base *ev_base, const struct console_config *config,
         const struct console_callbacks *callbacks, void *cb_arg, struct error_info *err)
 {
@@ -63,6 +88,9 @@
     // check it's not already initialized
     assert(!console->initialized);
 
+    // store
+    console->config = *config;
+
     // store callbacks?
     if (callbacks)
         console_set_callbacks(console, callbacks, cb_arg);
@@ -70,9 +98,16 @@
     // setup the input event
     if ((console->ev = event_new(ev_base, STDIN_FILENO, EV_READ | EV_PERSIST, &console_input, console)) == NULL)
         JUMP_SET_ERROR(err, ERR_EVENT_NEW);
+    
+    // set our SIGINT handler
+    struct sigaction sigact;
+    
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = on_sigint;
+    sigaction(SIGINT, &sigact, NULL);
 
     // setup readline
-    rl_callback_handler_install(config->prompt, &console_line);
+    rl_callback_handler_install(config->prompt, console_line);
     
     // mark it as initialized
     console->initialized = true;
--- a/src/console.h	Mon May 04 20:55:43 2009 +0300
+++ b/src/console.h	Mon May 04 23:19:50 2009 +0300
@@ -21,10 +21,15 @@
 struct console_callbacks {
     /**
      * A line was read from the console. 
-     *
-     * XXX: currently, line might be NULL on EOF, but this is probably a second callback
      */
     void (*on_line) (const char *line, void *arg);
+
+    /**
+     * EOF was read on the console.
+     *
+     * Note that for interactive consoles, EOF isn't actually EOF - there might be multiple EOFs...
+     */
+    void (*on_eof) (void *arg);
 };
 
 /**
@@ -41,13 +46,16 @@
  * You may replace the callbacks/cb_arg field with a new one at any time, using console_set_callbacks().
  */
 struct console {
-    /** The input event */
+    /** Configuration */
+    struct console_config config;
+
+    /** Input event */
     struct event *ev;
 
-    /** The callback functions */
+    /** Callback functions */
     const struct console_callbacks *callbacks;
 
-    /** The callback context argument */
+    /** Callback context argument */
     void *cb_arg;
 
     /** Already initialized? */
--- a/src/lua_console.c	Mon May 04 20:55:43 2009 +0300
+++ b/src/lua_console.c	Mon May 04 23:19:50 2009 +0300
@@ -23,8 +23,17 @@
      
 }
 
+static void lua_console_on_eof (void *arg)
+{
+    struct lua_console *lc = arg;
+
+    // exit the process
+    nexus_shutdown(lc->lua->nexus);
+}
+
 static struct console_callbacks _console_callbacks = {
-    .on_line    = &lua_console_on_line,
+    .on_line    = lua_console_on_line,
+    .on_eof     = lua_console_on_eof,
 };
 
 err_t lua_console_create (struct lua_console **lc_ptr, struct console *console, struct nexus_lua *lua, struct error_info *err)
--- a/src/nexus.c	Mon May 04 20:55:43 2009 +0300
+++ b/src/nexus.c	Mon May 04 23:19:50 2009 +0300
@@ -495,17 +495,25 @@
     memset(nexus, 0, sizeof(*nexus));
 }
 
-static void on_sigint (evutil_socket_t sig, short what, void *arg)
+static void on_sigterm (evutil_socket_t sig, short what, void *arg)
 {
     struct nexus *nexus = arg;
 
     (void) sig;
     (void) what;
     
-    log_info("Quitting...");
-    
-    // shutdown
-    nexus_shutdown(nexus);
+    if (!nexus->shutdown) {
+        // shutdown
+        log_info("Terminating...");
+
+        nexus_shutdown(nexus);
+
+    } else {
+        // already tried to shutdown
+        log_info("Crashing!");
+
+        nexus_crash(nexus);
+    }
 }
 
 int main (int argc, char **argv) 
@@ -527,11 +535,11 @@
  
     // add our signal handlers
     if (signal_ignore(SIGPIPE, &err))
-        FATAL_ERROR(&err, "signals_ignore(SIGPIPE)");
+        FATAL_ERROR(&err, "signals_ignore");
     
-    // XXX: add our SIGINT handler after console_init()?
-    if ((ERROR_CODE(&err) = signals_add(nexus->signals, SIGINT, &on_sigint, nexus)))
-        FATAL_ERROR(&err, "signals_add(SIGINT)");
+    // add our SIGTERM handler before console_init()?
+    if ((ERROR_CODE(&err) = signals_add(nexus->signals, SIGTERM, on_sigterm, nexus)))
+        FATAL_ERROR(&err, "signals_add");
  
 
     // initialize sock module
@@ -567,6 +575,8 @@
             FATAL("event_base_dispatch returned without shutdown");
 
         }
+    } else {
+        log_warn("zero return from event_base_dispatch");
     }
 
     // cleanup