Actual source code: signal.c
petsc-3.15.0 2021-03-30
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 application 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 (PetscDefined(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:   } else {
    156:     (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
    157:     (*PetscErrorPrintf)("to get more information on the crash.\n");
    158:   }
    159:    PetscError(PETSC_COMM_SELF,0,"User provided function"," unknown file",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
    160: #if !defined(PETSC_MISSING_SIGBUS)
    161:   if (sig == SIGSEGV || sig == SIGBUS) {
    162: #else
    163:   if (sig == SIGSEGV) {
    164: #endif
    165:     PetscBool debug;

    167:     PetscMallocGetDebug(&debug,NULL,NULL);
    168:     if (debug) {
    169:       (*PetscErrorPrintf)("Checking the memory for corruption.\n");
    170:       PetscMallocValidate(__LINE__,PETSC_FUNCTION_NAME,__FILE__);
    171:     } else {
    172:       (*PetscErrorPrintf)("Run with -malloc_debug to check if memory corruption is causing the crash.\n");
    173:     }
    174:   }
    175:   atexit(MyExit);
    176:   PETSCABORT(PETSC_COMM_WORLD,(int)ierr);
    177:   return(0);
    178: }

    180: #if !defined(PETSC_SIGNAL_CAST)
    181: #define PETSC_SIGNAL_CAST
    182: #endif

    184: /*@C
    185:    PetscPushSignalHandler - Catches the usual fatal errors and
    186:    calls a user-provided routine.

    188:    Not Collective

    190:     Input Parameter:
    191: +  routine - routine to call when a signal is received
    192: -  ctx - optional context needed by the routine

    194:   Level: developer

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

    198: @*/
    199: PetscErrorCode  PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
    200: {
    201:   struct  SH     *newsh;

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

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

    343:    Not Collective

    345:   Level: developer

    347: .seealso: PetscPushSignalHandler()

    349: @*/
    350: PetscErrorCode  PetscPopSignalHandler(void)
    351: {
    352:   struct SH      *tmp;

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

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