Changeset 147226 for trunk/base


Ignore:
Timestamp:
Mar 31, 2016, 4:59:52 PM (4 years ago)
Author:
raimue@…
Message:

pextlib/system: custom handler for SIGINT/SIGQUIT

Record the fact that a signal was delivered and throw the appropriate error
code, This will still block until the child process terminates itself.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/base/src/pextlib1.0/system.c

    r147224 r147226  
    110110}
    111111
     112static volatile int interrupted_by = 0;
     113static void handle_sigint(int s) {
     114    interrupted_by = s;
     115}
     116
    112117/* usage: system ?-notty? ?-nodup? ?-nice value? ?-W path? command */
    113118int SystemCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
     
    190195
    191196    /*
    192      * Ignore SIGINT and SIGQUIT, just like system(3)
     197     * Custom handlers for SIGINT and SIGQUIT to detect aborts
    193198     *
    194199     * system(3) also blocks SIGCHLD during the execution of the program.
     
    199204    struct sigaction sa, old_sa_int, old_sa_quit;
    200205    memset(&sa, 0, sizeof(sa));
    201     sa.sa_handler = SIG_IGN;
     206    sa.sa_handler = handle_sigint;
    202207    sigemptyset(&sa.sa_mask);
     208    sa.sa_flags = SA_RESTART;
     209    interrupted_by = 0;
    203210    sigaction(SIGINT, &sa, &old_sa_int);
    204211    sigaction(SIGQUIT, &sa, &old_sa_quit);
     
    345352
    346353            errorCode = Tcl_NewListObj(0, NULL);
    347             if (WIFEXITED(ret)) {
     354            if (interrupted_by != 0) {
     355                /* set errorCode [list POSIX SIG <SIGNAME> <signal descripton>] */
     356                Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewStringObj("POSIX", -1));
     357                Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewStringObj("SIG", -1));
     358                Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewStringObj(Tcl_SignalId(interrupted_by), -1));
     359                Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewStringObj(Tcl_SignalMsg(interrupted_by), -1));
     360                Tcl_SetObjErrorCode(interp, errorCode);
     361                Tcl_SetObjResult(interp, Tcl_NewStringObj("interrupted by signal", -1));
     362            } else if (WIFEXITED(ret)) {
    348363                /* set errorCode [list CHILDSTATUS <pid> <code>] */
    349364                Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewStringObj("CHILDSTATUS", -1));
     
    351366                Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewIntObj(WEXITSTATUS(ret)));
    352367                Tcl_SetObjErrorCode(interp, errorCode);
     368                Tcl_SetObjResult(interp, Tcl_NewStringObj("command execution failed", -1));
    353369            } else if (WIFSIGNALED(ret)) {
    354370                /* set errorCode [list CHILDKILLED <pid> <SIGNAME> <signal descripton>] */
     
    358374                Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewStringObj(Tcl_SignalMsg(WTERMSIG(ret)), -1));
    359375                Tcl_SetObjErrorCode(interp, errorCode);
    360             }
    361 
    362             Tcl_SetObjResult(interp, Tcl_NewStringObj("command execution failed", -1));
     376                Tcl_SetObjResult(interp, Tcl_NewStringObj("command execution failed", -1));
     377            }
    363378        }
    364379    }
Note: See TracChangeset for help on using the changeset viewer.