From e230929a579d7f91df7d34a4c0a324fb8dd5fa4a Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Mon, 22 Sep 2014 20:44:42 -0700 Subject: [PATCH] NSM Proxy: Detect, log, and display startup errors of proxied process. --- session-manager/src/nsm-proxy-gui.C | 56 ++++++++++++++++++++++ session-manager/src/nsm-proxy.C | 74 ++++++++++++++++++++++++----- 2 files changed, 119 insertions(+), 11 deletions(-) diff --git a/session-manager/src/nsm-proxy-gui.C b/session-manager/src/nsm-proxy-gui.C index 2196cfc..ef02972 100644 --- a/session-manager/src/nsm-proxy-gui.C +++ b/session-manager/src/nsm-proxy-gui.C @@ -26,6 +26,7 @@ #define APP_TITLE "NSM Proxy" #include +#include #include "NSM_Proxy_UI.H" #include #include @@ -38,6 +39,8 @@ lo_address nsmp_addr; static NSM_Proxy_UI *ui; +static char *client_error; + int osc_update ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data ) { @@ -73,6 +76,16 @@ osc_update ( const char *path, const char *types, lo_arg **argv, int argc, lo_me else if ( argv[0]->i == SIGHUP ) ui->stop_signal_choice->value( 2 ); } + if (!strcmp( path, "/nsm/proxy/client_error" )) + { + if ( client_error != NULL ) + free(client_error); + + client_error = NULL; + + if ( strlen(&argv[0]->s) > 0 ) + client_error = strdup(&argv[0]->s); + } Fl::unlock(); @@ -101,6 +114,7 @@ init_osc ( const char *osc_port ) lo_server_thread_add_method( loth, "/nsm/proxy/label", "s", osc_update, NULL ); lo_server_thread_add_method( loth, "/nsm/proxy/save_signal", "i", osc_update, NULL ); lo_server_thread_add_method( loth, "/nsm/proxy/stop_signal", "i", osc_update, NULL ); + lo_server_thread_add_method( loth, "/nsm/proxy/client_error", "s", osc_update, NULL ); lo_server_thread_start( loth ); } @@ -202,6 +216,46 @@ connect_ui ( void ) +void cb_dismiss_button ( Fl_Widget *w, void *v ) +{ + w->window()->hide(); +} + +void +check_error ( void *v ) +{ + if ( client_error ) + { + { + Fl_Double_Window *o = new Fl_Double_Window(600,300+15,"Abnormal Termination"); + { + Fl_Box *o = new Fl_Box(0+15,0+15,600-30,50); + o->box(FL_BORDER_BOX); + o->color(FL_RED); + o->labelcolor(FL_WHITE); + o->align(FL_ALIGN_CENTER|FL_ALIGN_WRAP); + o->copy_label( client_error ); + } + { + Fl_Text_Display *o = new Fl_Text_Display(0+15,50+15,600-30,300-75-30); + o->buffer(new Fl_Text_Buffer()); + o->buffer()->loadfile( "error.log" ); + } + { + Fl_Button *o = new Fl_Button(600-75-15,300-25,75,25,"Dismiss"); + o->callback(cb_dismiss_button,0); + } + + o->show(); + } + + free(client_error); + client_error = NULL; + } + + Fl::repeat_timeout( 0.5f, check_error, v ); +} + int main ( int argc, char **argv ) { @@ -229,6 +283,8 @@ main ( int argc, char **argv ) Fl::lock(); + Fl::add_timeout( 0.5f, check_error, NULL ); + Fl::run(); return 0; diff --git a/session-manager/src/nsm-proxy.C b/session-manager/src/nsm-proxy.C index 8b0a98f..a007b0c 100644 --- a/session-manager/src/nsm-proxy.C +++ b/session-manager/src/nsm-proxy.C @@ -51,6 +51,7 @@ static char *nsm_display_name; #define CONFIG_FILE_NAME "nsm-proxy.config" +void show_gui ( void ); class NSM_Proxy { @@ -61,25 +62,46 @@ class NSM_Proxy { int _save_signal; int _stop_signal; int _pid; + char *_client_error; public: + int stop_signal ( void ) {return _stop_signal;} + NSM_Proxy ( ) { _label = _executable = _arguments = _config_file = 0; _save_signal = 0; _stop_signal = SIGTERM; _pid = 0; + _client_error = 0; } ~NSM_Proxy ( ) { } - + + void handle_client_death ( int status ) + { + printf( "proxied process died unexpectedly... not dying\n" ); + /* proxied process died unexpectedly */ + + if ( _client_error != NULL ) + free(_client_error); + + asprintf(&_client_error, "The proxied process terminated abnormally during invocation. Exit status: %i.", status ); + + show_gui(); + + _pid = 0; + } + void kill ( void ) { if ( _pid ) + { ::kill( _pid, _stop_signal ); + } } bool start ( const char *executable, const char *arguments, const char *config_file ) @@ -130,11 +152,11 @@ public: char *cmd; if ( _arguments ) - asprintf( &cmd, "exec %s %s", _executable, _arguments ); + asprintf( &cmd, "exec %s %s >error.log 2>&1", _executable, _arguments ); else - asprintf( &cmd, "exec %s", _executable ); + asprintf( &cmd, "exec %s >error.log 2>&1", _executable ); - char *args[] = { _executable, strdup( "-c" ), cmd, NULL }; + char *args[] = { strdup("/bin/sh"), strdup( "-c" ), cmd, NULL }; setenv( "NSM_CLIENT_ID", nsm_client_id, 1 ); setenv( "NSM_SESSION_NAME", nsm_display_name, 1 ); @@ -145,8 +167,7 @@ public: if ( -1 == execvp( "/bin/sh", args ) ) { WARNING( "Error starting process: %s", strerror( errno ) ); - - exit(-1); + exit(1); } } @@ -222,7 +243,6 @@ public: bool restore ( const char *path ) { FILE *fp = fopen( path, "r" ); - if ( ! fp ) { WARNING( "Error opening file for restore: %s", strerror( errno ) ); @@ -285,6 +305,9 @@ public: lo_send_from( to, losrv, LO_TT_IMMEDIATE, "/nsm/proxy/arguments", "s", _arguments ? _arguments : "" ); lo_send_from( to, losrv, LO_TT_IMMEDIATE, "/nsm/proxy/config_file", "s", _config_file ? _config_file : "" ); lo_send_from( to, losrv, LO_TT_IMMEDIATE, "/nsm/proxy/stop_signal", "i", _stop_signal ); + lo_send_from( to, losrv, LO_TT_IMMEDIATE, "/nsm/proxy/client_error", "s", _client_error ? _client_error : "" ); + + } }; @@ -400,7 +423,7 @@ show_gui ( void ) { WARNING( "Error starting process: %s", strerror( errno ) ); - exit(-1); + exit(1); } } @@ -649,10 +672,39 @@ void handle_sigchld ( ) continue; } - /* otherwise, it was our proxied process that died, so we should die too */ - printf( "proxied process died... nsm-proxy dying too\n" ); + if ( WIFSIGNALED(status) ) + { + /* process was killed via signal */ + if (WTERMSIG(status) == SIGTERM || + WTERMSIG(status) == SIGHUP || + WTERMSIG(status) == SIGINT || + WTERMSIG(status) == SIGKILL ) + { + /* process was killed via an appropriate signal */ + MESSAGE( "child was killed (maybe by us)\n" ); + die_now = 1; + continue; + } + } + else if ( WIFEXITED(status) ) + { + /* child called exit() or returned from main() */ - die_now = 1; + MESSAGE( "child exit status: %i", WEXITSTATUS(status) ); + + if ( WEXITSTATUS(status) == 0 ) + { + /* apparently normal termination */ + MESSAGE( "child exited without error."); + die_now = 1; + continue; + } + else + { + MESSAGE("child exited abnormally."); + nsm_proxy->handle_client_death(WEXITSTATUS(status)); + } + } } }