Actual source code: signal.c
petsc-3.13.6 2020-09-29
Report Typos and Errors

      2: /*
      3:       Routines to handle signals the program will receive.
      4:     Usually this will call the error handlers.
      5: */
      6:  #include <petsc/private/petscimpl.h>
      7: #include <signal.h>
      8: #include <stdlib.h> /* for _Exit() */

     10: static PetscClassId SIGNAL_CLASSID = 0;

     12: struct SH {
     13:   PetscClassId   classid;
     14:   PetscErrorCode (*handler)(int,void*);
     15:   void           *ctx;
     16:   struct SH      *previous;
     17: };
     18: static struct SH *sh       = NULL;
     19: static PetscBool SignalSet = PETSC_FALSE;

     21: /* Called by MPI_Abort() to suppress user-registered atexit()/on_exit() functions.
     22:    See discussion at https://gitlab.com/petsc/petsc/-/merge_requests/2745.
     23: */
     24: static void MyExit(void)
     25: {
     26:   _Exit(MPI_ERR_OTHER);
     27: }

     29: /*
     30:     PetscSignalHandler_Private - This is the signal handler called by the system. This calls
     31:              any signal handler set by PETSc or the Section 1.5 Writing Application Codes with PETSc code.

     33:    Input Parameters: (depends on system)
     34: .    sig - integer code indicating the type of signal
     35: .    code - ??
     36: .    sigcontext - ??
     37: .    addr - ??

     39: */
     40: #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER)
     41: static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr)
     42: #else
     43: static void PetscSignalHandler_Private(int sig)
     44: #endif
     45: {

     49:   if (!sh || !sh->handler) PetscSignalHandlerDefault(sig,(void*)0);
     50:   else {
     51:     if (sh->classid != SIGNAL_CLASSID) SETERRABORT(PETSC_COMM_WORLD,PETSC_ERR_COR,"Signal object has been corrupted");
     52:     (*sh->handler)(sig,sh->ctx);
     53:   }
     54:   if (ierr) PETSCABORT(PETSC_COMM_WORLD,PETSC_ERR_COR);
     55: }

     57: /*@
     58:    PetscSignalHandlerDefault - Default signal handler.

     60:    Not Collective

     62:    Level: advanced

     64:    Input Parameters:
     65: +  sig - signal value
     66: -  ptr - unused pointer

     68: @*/
     69: PetscErrorCode  PetscSignalHandlerDefault(int sig,void *ptr)
     70: {
     72:   const char     *SIGNAME[64];

     75:   if (sig == SIGSEGV) PetscSignalSegvCheckPointerOrMpi();
     76:   SIGNAME[0]       = "Unknown signal";
     77: #if !defined(PETSC_MISSING_SIGABRT)
     78:   SIGNAME[SIGABRT] = "Abort";
     79: #endif
     80: #if !defined(PETSC_MISSING_SIGALRM)
     81:   SIGNAME[SIGALRM] = "Alarm";
     82: #endif
     83: #if !defined(PETSC_MISSING_SIGBUS)
     84:   SIGNAME[SIGBUS]  = "BUS: Bus Error, possibly illegal memory access";
     85: #endif
     86: #if !defined(PETSC_MISSING_SIGCHLD)
     87:   SIGNAME[SIGCHLD] = "CHLD";
     88: #endif
     89: #if !defined(PETSC_MISSING_SIGCONT)
     90:   SIGNAME[SIGCONT] = "CONT";
     91: #endif
     92: #if !defined(PETSC_MISSING_SIGFPE)
     93:   SIGNAME[SIGFPE]  = "FPE: Floating Point Exception,probably divide by zero";
     94: #endif
     95: #if !defined(PETSC_MISSING_SIGHUP)
     96:   SIGNAME[SIGHUP]  = "Hang up: Some other process (or the batch system) has told this process to end";
     97: #endif
     98: #if !defined(PETSC_MISSING_SIGILL)
     99:   SIGNAME[SIGILL]  = "Illegal instruction: Likely due to memory corruption";
    100: #endif
    101: #if !defined(PETSC_MISSING_SIGINT)
    102:   SIGNAME[SIGINT]  = "Interrupt";
    103: #endif
    104: #if !defined(PETSC_MISSING_SIGKILL)
    105:   SIGNAME[SIGKILL] = "Kill: Some other process (or the batch system) has told this process to end";
    106: #endif
    107: #if !defined(PETSC_MISSING_SIGPIPE)
    108:   SIGNAME[SIGPIPE] = "Broken Pipe: Likely while reading or writing to a socket";
    109: #endif
    110: #if !defined(PETSC_MISSING_SIGQUIT)
    111:   SIGNAME[SIGQUIT] = "Quit: Some other process (or the batch system) has told this process to end";
    112: #endif
    113: #if !defined(PETSC_MISSING_SIGSEGV)
    114:   SIGNAME[SIGSEGV] = "SEGV: Segmentation Violation, probably memory access out of range";
    115: #endif
    116: #if !defined(PETSC_MISSING_SIGSYS)
    117:   SIGNAME[SIGSYS]  = "SYS";
    118: #endif
    119: #if !defined(PETSC_MISSING_SIGTERM)
    120:   SIGNAME[SIGTERM] = "Terminate: Some process (or the batch system) has told this process to end";
    121: #endif
    122: #if !defined(PETSC_MISSING_SIGTRAP)
    123:   SIGNAME[SIGTRAP] = "TRAP";
    124: #endif
    125: #if !defined(PETSC_MISSING_SIGTSTP)
    126:   SIGNAME[SIGTSTP] = "TSTP";
    127: #endif
    128: #if !defined(PETSC_MISSING_SIGURG)
    129:   SIGNAME[SIGURG]  = "URG";
    130: #endif
    131: #if !defined(PETSC_MISSING_SIGUSR1)
    132:   SIGNAME[SIGUSR1] = "User 1";
    133: #endif
    134: #if !defined(PETSC_MISSING_SIGUSR2)
    135:   SIGNAME[SIGUSR2] = "User 2";
    136: #endif

    138:   signal(sig,SIG_DFL);
    139:   (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
    140:   if (sig >= 0 && sig <= 20) (*PetscErrorPrintf)("Caught signal number %d %s\n",sig,SIGNAME[sig]);
    141:   else (*PetscErrorPrintf)("Caught signal\n");

    143:   (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
    144:   (*PetscErrorPrintf)("or see https://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind\n");
    145:   (*PetscErrorPrintf)("or try http://valgrind.org on GNU/linux and Apple Mac OS X to find memory corruption errors\n");
    146: #if defined(PETSC_USE_DEBUG)
    147:   if (!PetscStackActive()) (*PetscErrorPrintf)("  or try option -log_stack\n");
    148:   else {
    149:     PetscStackPop;  /* remove stack frames for error handlers */
    150:     PetscStackPop;
    151:     (*PetscErrorPrintf)("likely location of problem given in stack below\n");
    152:     (*PetscErrorPrintf)("---------------------  Stack Frames ------------------------------------\n");
    153:     PetscStackView(PETSC_STDOUT);
    154:   }
    155: #endif
    156: #if !defined(PETSC_USE_DEBUG)
    157:   (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
    158:   (*PetscErrorPrintf)("to get more information on the crash.\n");
    159: #endif
    160:    PetscError(PETSC_COMM_SELF,0,"User provided function"," unknown file",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
    161:   atexit(MyExit);
    162:   PETSCABORT(PETSC_COMM_WORLD,(int)ierr);
    163:   return(0);
    164: }

    166: #if !defined(PETSC_SIGNAL_CAST)
    167: #define PETSC_SIGNAL_CAST
    168: #endif

    170: /*@C
    171:    PetscPushSignalHandler - Catches the usual fatal errors and
    172:    calls a user-provided routine.

    174:    Not Collective

    176:     Input Parameter:
    177: +  routine - routine to call when a signal is received
    178: -  ctx - optional context needed by the routine

    180:   Level: developer

    182: .seealso: PetscPopSignalHandler(), PetscSignalHandlerDefault(), PetscPushErrorHandler()

    184: @*/
    185: PetscErrorCode  PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
    186: {
    187:   struct  SH     *newsh;

    191:   if (!SIGNAL_CLASSID) {
    192:     /* PetscClassIdRegister("Signal",&SIGNAL_CLASSID); */
    193:     SIGNAL_CLASSID = 19;
    194:   }
    195:   if (!SignalSet && routine) {
    196:     /* Do not catch ABRT, CHLD, KILL */
    197: #if !defined(PETSC_MISSING_SIGALRM)
    198:     /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
    199: #endif
    200: #if !defined(PETSC_MISSING_SIGBUS)
    201:     signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    202: #endif
    203: #if !defined(PETSC_MISSING_SIGCONT)
    204:     /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/
    205: #endif
    206: #if !defined(PETSC_MISSING_SIGFPE)
    207:     signal(SIGFPE,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    208: #endif
    209: #if !defined(PETSC_MISSING_SIGHUP) && defined(PETSC_HAVE_STRUCT_SIGACTION)
    210:     {
    211:       struct  sigaction action;
    212:       sigaction(SIGHUP,NULL,&action);
    213:       if (action.sa_handler == SIG_IGN) {
    214:         PetscInfo(NULL,"SIGHUP previously set to ignore, therefor not changing its signal handler\n");
    215:       } else {
    216:         signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    217:       }
    218:     }
    219: #endif
    220: #if !defined(PETSC_MISSING_SIGILL)
    221:     signal(SIGILL,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    222: #endif
    223: #if !defined(PETSC_MISSING_SIGINT)
    224:     /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
    225: #endif
    226: #if !defined(PETSC_MISSING_SIGPIPE)
    227:     signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    228: #endif
    229: #if !defined(PETSC_MISSING_SIGQUIT)
    230:     signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    231: #endif
    232: #if !defined(PETSC_MISSING_SIGSEGV)
    233:     signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    234: #endif
    235: #if !defined(PETSC_MISSING_SIGSYS)
    236:     signal(SIGSYS,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    237: #endif
    238: #if !defined(PETSC_MISSING_SIGTERM)
    239:     signal(SIGTERM,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    240: #endif
    241: #if !defined(PETSC_MISSING_SIGTRAP)
    242:     signal(SIGTRAP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    243: #endif
    244: #if !defined(PETSC_MISSING_SIGTSTP)
    245:     /* signal(SIGTSTP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
    246: #endif
    247: #if !defined(PETSC_MISSING_SIGURG)
    248:     signal(SIGURG,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
    249: #endif
    250: #if !defined(PETSC_MISSING_SIGUSR1)
    251:     /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
    252: #endif
    253: #if !defined(PETSC_MISSING_SIGUSR2)
    254:     /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
    255: #endif
    256:     SignalSet = PETSC_TRUE;
    257:   }
    258:   if (!routine) {
    259: #if !defined(PETSC_MISSING_SIGALRM)
    260:     /* signal(SIGALRM, SIG_DFL); */
    261: #endif
    262: #if !defined(PETSC_MISSING_SIGBUS)
    263:     signal(SIGBUS,  SIG_DFL);
    264: #endif
    265: #if !defined(PETSC_MISSING_SIGCONT)
    266:     /* signal(SIGCONT, SIG_DFL); */
    267: #endif
    268: #if !defined(PETSC_MISSING_SIGFPE)
    269:     signal(SIGFPE,  SIG_DFL);
    270: #endif
    271: #if !defined(PETSC_MISSING_SIGHUP)
    272:     signal(SIGHUP,  SIG_DFL);
    273: #endif
    274: #if !defined(PETSC_MISSING_SIGILL)
    275:     signal(SIGILL,  SIG_DFL);
    276: #endif
    277: #if !defined(PETSC_MISSING_SIGINT)
    278:     /* signal(SIGINT,  SIG_DFL); */
    279: #endif
    280: #if !defined(PETSC_MISSING_SIGPIPE)
    281:     signal(SIGPIPE, SIG_DFL);
    282: #endif
    283: #if !defined(PETSC_MISSING_SIGQUIT)
    284:     signal(SIGQUIT, SIG_DFL);
    285: #endif
    286: #if !defined(PETSC_MISSING_SIGSEGV)
    287:     signal(SIGSEGV, SIG_DFL);
    288: #endif
    289: #if !defined(PETSC_MISSING_SIGSYS)
    290:     signal(SIGSYS,  SIG_DFL);
    291: #endif
    292: #if !defined(PETSC_MISSING_SIGTERM)
    293:     signal(SIGTERM, SIG_DFL);
    294: #endif
    295: #if !defined(PETSC_MISSING_SIGTRAP)
    296:     signal(SIGTRAP, SIG_DFL);
    297: #endif
    298: #if !defined(PETSC_MISSING_SIGTSTP)
    299:     /* signal(SIGTSTP, SIG_DFL); */
    300: #endif
    301: #if !defined(PETSC_MISSING_SIGURG)
    302:     signal(SIGURG,  SIG_DFL);
    303: #endif
    304: #if !defined(PETSC_MISSING_SIGUSR1)
    305:     /* signal(SIGUSR1, SIG_DFL); */
    306: #endif
    307: #if !defined(PETSC_MISSING_SIGUSR2)
    308:     /* signal(SIGUSR2, SIG_DFL); */
    309: #endif
    310:     SignalSet = PETSC_FALSE;
    311:   }
    312:   PetscNew(&newsh);
    313:   if (sh) {
    314:     if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
    315:     newsh->previous = sh;
    316:   }  else newsh->previous = NULL;
    317:   newsh->handler = routine;
    318:   newsh->ctx     = ctx;
    319:   newsh->classid = SIGNAL_CLASSID;
    320:   sh             = newsh;
    321:   return(0);
    322: }

    324: /*@
    325:    PetscPopSignalHandler - Removes the most last signal handler that was pushed.
    326:        If no signal handlers are left on the stack it will remove the PETSc signal handler.
    327:        (That is PETSc will no longer catch signals).

    329:    Not Collective

    331:   Level: developer

    333: .seealso: PetscPushSignalHandler()

    335: @*/
    336: PetscErrorCode  PetscPopSignalHandler(void)
    337: {
    338:   struct SH      *tmp;

    342:   if (!sh) return(0);
    343:   if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");

    345:   tmp = sh;
    346:   sh  = sh->previous;
    347:   PetscFree(tmp);
    348:   if (!sh || !sh->handler) {
    349: #if !defined(PETSC_MISSING_SIGALRM)
    350:     /* signal(SIGALRM, SIG_DFL); */
    351: #endif
    352: #if !defined(PETSC_MISSING_SIGBUS)
    353:     signal(SIGBUS,  SIG_DFL);
    354: #endif
    355: #if !defined(PETSC_MISSING_SIGCONT)
    356:     /* signal(SIGCONT, SIG_DFL); */
    357: #endif
    358: #if !defined(PETSC_MISSING_SIGFPE)
    359:     signal(SIGFPE,  SIG_DFL);
    360: #endif
    361: #if !defined(PETSC_MISSING_SIGHUP)
    362:     signal(SIGHUP,  SIG_DFL);
    363: #endif
    364: #if !defined(PETSC_MISSING_SIGILL)
    365:     signal(SIGILL,  SIG_DFL);
    366: #endif
    367: #if !defined(PETSC_MISSING_SIGINT)
    368:     /* signal(SIGINT,  SIG_DFL); */
    369: #endif
    370: #if !defined(PETSC_MISSING_SIGPIPE)
    371:     signal(SIGPIPE, SIG_DFL);
    372: #endif
    373: #if !defined(PETSC_MISSING_SIGQUIT)
    374:     signal(SIGQUIT, SIG_DFL);
    375: #endif
    376: #if !defined(PETSC_MISSING_SIGSEGV)
    377:     signal(SIGSEGV, SIG_DFL);
    378: #endif
    379: #if !defined(PETSC_MISSING_SIGSYS)
    380:     signal(SIGSYS,  SIG_DFL);
    381: #endif
    382: #if !defined(PETSC_MISSING_SIGTERM)
    383:     signal(SIGTERM, SIG_DFL);
    384: #endif
    385: #if !defined(PETSC_MISSING_SIGTRAP)
    386:     signal(SIGTRAP, SIG_DFL);
    387: #endif
    388: #if !defined(PETSC_MISSING_SIGTSTP)
    389:     /* signal(SIGTSTP, SIG_DFL); */
    390: #endif
    391: #if !defined(PETSC_MISSING_SIGURG)
    392:     signal(SIGURG,  SIG_DFL);
    393: #endif
    394: #if !defined(PETSC_MISSING_SIGUSR1)
    395:     /* signal(SIGUSR1, SIG_DFL); */
    396: #endif
    397: #if !defined(PETSC_MISSING_SIGUSR2)
    398:     /* signal(SIGUSR2, SIG_DFL); */
    399: #endif
    400:     SignalSet = PETSC_FALSE;
    401:   } else {
    402:     SignalSet = PETSC_TRUE;
    403:   }
    404:   return(0);
    405: }