/* */
        
int ServerSetSignalHandlers()

  {
  /* trap TERM(15) QUIT(3) INT(2) HUP(1) */
 
#if defined(__AIX41) || defined(__AIX42) || defined(__AIX43) || defined(__AIX51) || defined(__IRIX) || defined(__LINUX) || defined(__CYGWIN) || defined(__HPUX) || defined(__SOLARIS) || defined(__OSF) || defined(__FREEBSD)
 
  signal(SIGINT,   SIG_IGN);
  signal(SIGTERM,  (void(*)(int))MSysShutdown);
  signal(SIGQUIT,  (void(*)(int))MSysShutdown);
  signal(SIGIO,    (void(*)(int))MSysShutdown);
  signal(SIGURG,   (void(*)(int))MSysShutdown);
 
#else /* ... */
 
  signal(SIGINT,   SIG_IGN);
  signal(SIGTERM,  MSysShutdown);
  signal(SIGQUIT,  MSysShutdown);
  signal(SIGIO,    MSysShutdown);
  signal(SIGURG,   MSysShutdown);
 
#endif /* ... */
 
  /* handle SIGPIPE/SIGHUP/SIGSEGV/SIGILL */
 
#if defined(__AIX41) || defined(__AIX42) || defined(__AIX43) || defined(__AIX51)

  {
  char             *ptr;
  struct sigaction  act;

  act.sa_handler = SIG_IGN;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;
 
  if (sigaction(SIGPIPE,&act,NULL) == -1) 
    {
    DBG(0,fCORE) DPrint("ERROR:    cannot ignore SIGPIPE, errno: %d (%s)\n",
      errno,
      strerror(errno));
    }
 
/* NOTE:  HUP temporarily disabled
  signal(SIGHUP,   (void(*)(int))ReloadConfig);
*/
  signal(SIGHUP,SIG_IGN);
 
  /* set up SIGSEGV and SIGILL signal handlers */
 
  sigaction(SIGSEGV,0,&act);
 
  act.sa_flags |= SA_FULLDUMP;
 
  if ((ptr = getenv(MSCHED_ENVCRASHVAR)) == NULL)
    {
    act.sa_handler = (void(*)(int))SIG_DFL;
    }
  else if (!strcasecmp(ptr,"trap"))
    {
    act.sa_handler = (void(*)(int))CrashMode;
    }
  else if (!strcasecmp(ptr,"ignore"))
    {
    act.sa_handler = (void(*)(int))SIG_IGN;
    }
  else if (!strcasecmp(ptr,"die"))
    {
    act.sa_handler = (void(*)(int))SIG_DFL;
    }
  else
    {
    act.sa_handler = (void(*)(int))ServerRestart;
    } 
 
  /* create full core dumps on SEGV and ILL */
 
  if (sigaction(SIGSEGV,&act,NULL) < 0)
    {
    perror("cannot set up SIGSEGV signal handler");
 
    DBG(0,fALL) DPrint("ERROR:    cannot set up SEGV error handler, errno: %d (%s)\n",
      errno,
      strerror(errno));
    }
 
  sigaction(SIGILL,0,&act);
 
  act.sa_flags |= SA_FULLDUMP;
 
  if ((ptr = getenv(MSCHED_ENVCRASHVAR)) == NULL)
    {
    act.sa_handler = (void(*)(int))SIG_DFL;
    }
  else if (!strcasecmp(ptr,"trap"))
    {
    act.sa_handler = (void(*)(int))CrashMode;
    }
  else if (!strcasecmp(ptr,"ignore"))
    {
    act.sa_handler = (void(*)(int))SIG_IGN;
    }
  else if (!strcasecmp(ptr,"die"))
    {
    act.sa_handler = (void(*)(int))SIG_DFL;
    }
  else
    {
    act.sa_handler = (void(*)(int))ServerRestart;
    } 
 
  if (sigaction(SIGILL,&act,NULL) < 0)
    {
    perror("cannot set up SIGILL signal handler");
 
    DBG(0,fALL) DPrint("ERROR:    cannot set up SIGILL signal handler, errno: %d (%s)\n",
      errno,
      strerror(errno));
    }
  }    /* END BLOCK */ 

#elif defined(__LINUX) || defined(__CYGWIN) || defined(__IRIX) || defined(__HPUX) || defined(__SOLARIS) || defined(__OSF)

  ServerLoadSignalConfig();
 
#else /* PIPE/HUP/SEGV */
 
/* NOTE: HUP temporarily disabled  *
  signal(SIGHUP,   (void(*)(int))ReloadConfig);
*/
  signal(SIGHUP,   SIG_IGN);
  signal(SIGPIPE,  SIG_IGN);
  signal(SIGSEGV,  MSysShutdown);
  signal(SIGILL,   MSysShutdown);
 
#endif /* PIPE/HUP/SEGV */

  return(SUCCESS);
  }  /* END ServerSetSignalHandlers() */




int ServerDemonize()
{
#ifndef __CYGRUNSRV

#ifndef __NT
  int   pid;
#endif /* __NT */

  FILE *fp;

  const char *FName = "ServerDemonize";

  DBG(2,fALL) DPrint("%s()\n",
    FName);

  /* create private process group */

  if (MSched.Mode != msmSim)
    {
#if !defined(__NT) && !defined(__HPUX)
#if defined(__OSF) || defined(__FREEBSD)
    if (setpgrp((pid_t)0,(pid_t)0) == -1)
#else /* __OSF */
    if (setpgrp() == -1)
#endif /* __OSF */
      {
      perror("cannot set process group");

      DBG(0,fALL) DPrint("ERROR:    cannot setpgrp, errno: %d (%s)\n",
        errno,
        strerror(errno));
      }
#endif /* !defined(__NT) && !defined(__HPUX) */

    fflush(mlog.logfp);

    if (MSched.DebugMode == FALSE)
      {
      /* only background if not in debug mode */

      /* NOTE:  setsid() disconnects from controlling-terminal */

#ifndef __NT

      if ((pid = fork()) == -1)
        {
        perror("cannot fork");

        DBG(0,fALL) DPrint("ALERT:    cannot fork into background, errno: %d (%s)\n",
          errno,
          strerror(errno));
        }

      if (pid != 0)
        {
        /* exit if parent */

        DBG(3,fALL) DPrint("INFO:     parent is exiting\n");

        fflush(mlog.logfp);

        exit(0);
        }
      else
        {
        DBG(3,fALL) DPrint("INFO:     child process in background\n");
        }

      if (setsid() == -1)
        {
        MDB(3,fALL) MLog("INFO:     could not disconnect from controlling-terminal, errno=%d - %s\n",
          errno,
          strerror(errno));
        }

      /* disconnect stdin */

      fclose(stdin);
      fp = fopen("/dev/null","r");

      /* disconnect stdout */

      fclose(stdout);
      fp = fopen("/dev/null","w");

      /* disconnect stderr */

      fclose(stderr);
      fp = fopen("/dev/null","w");

#endif /* __NT */
      }
    }    /* END if (MSched.Mode != msmSim) */

#endif /* __CYGRUNSRV */
  return(SUCCESS);
  }  /* END ServerDemonize() */






int CrashMode(

  int signo)

  {
  long   Time;
  time_t tmpTime;

  char Line[MAX_MLINE];

  DBG(1,fALL) DPrint("CrashMode(%d)\n",
    signo);

  MSched.Schedule = FALSE;

  MSched.CrashMode = TRUE;

  time(&tmpTime);
  Time = (long)tmpTime;

  DBG(1,fALL) DPrint("CRASH MODE:  crash occurred on iteration %d (Debug: %d) time: %s\n",
    MSched.Iteration,
    mlog.Threshold,
    MULToDString((mulong *)&Time));
 
  if (MSched.Mode == msmSim)
    {
    DBG(1,fALL) DPrint("CRASH MODE:  SIMULATION TIME: (%ld) %s\n",
      MSched.Time,
      MULToDString((mulong *)&MSched.Time));
    }

  mlog.Threshold = 20;

  if (MSched.Mode == msmNormal)
    {
    MOSSyslog(LOG_ERR,"ERROR:  %s has crashed, signo: %d",
      MSCHED_SNAME,
      signo);
    }

  sprintf(Line,"scheduler has crashed.  Signo: %d",
    signo);

  MSysRegEvent(Line,0,0,1);

  fflush(mlog.logfp);

  /* save log file */

  MLogRoll(".crash",1,MSched.Iteration,MSched.LogFileRollDepth);

  fprintf(stderr,"ALERT:    created crash file\n");

  sleep(2);

  DBG(1,fALL) DPrint("CRASH MODE:  attempting to read socket connection\n");

  UIProcessClients(&MSched.ServerS,MSched.RMPollInterval);

  if (signo == SIGSEGV)
    {
#if defined(__AIX41) || defined(__AIX42) || defined(__AIX43) || defined(__AIX51) || defined(__LINUX) || defined(__CYGWIN) || defined(__CYGWIN) || defined(__HPUX) || defined(__IRIX) || defined(__SOLARIS) || defined(__OSF) || defined(__FREEBSD)

    signal(SIGSEGV,(void(*)(int))CrashMode);

#else

    signal(SIGSEGV,(CrashMode));

#endif
    }
  else if (signo == SIGILL)
    {
#if defined(__AIX41) || defined(__AIX42) || defined(__AIX43) || defined(__AIX51) || defined(__LINUX) || defined(__CYGWIN) || defined(__HPUX) || defined(__IRIX) || defined(__SOLARIS) || defined(__OSF) || defined(__FREEBSD)

    signal(SIGILL,(void(*)(int))CrashMode);

#else

    signal(SIGILL,(CrashMode));

#endif
    }

  DBG(0,fALL) DPrint("INFO:     exiting CRASH MODE\n");

  return(SUCCESS);
  }  /* END CrashMode() */




void ServerRestart(

  int signo)

  {
  int  rc;

  const char *FName = "ServerRestart";

  DBG(1,fALL) DPrint("%s(%d)\n",
    FName,
    signo);

  if ((rc = execv(MSched.Argv[0],MSched.Argv)) == -1)
    {
    /* exec failed */

    DBG(1,fCORE) DPrint("ERROR:    cannot restart scheduler '%s' rc: %d\n",
      MSched.Argv[0],
      rc);

    exit(1);
    }

  exit(0);
  }  /* END ServerRestart() */




int ReloadConfig(

  int signo)

  {
  DBG(2,fCONFIG) DPrint("ReloadConfig()\n");

  DBG(1,fCONFIG) DPrint("INFO:     received signal %d.  reloading config at next interval\n",
    signo);

  MSched.Reload = TRUE;

#if defined(__AIX41) || defined(__AIX42) || defined(__AIX43) || defined(__AIX51) || defined(__LINUX) || defined(__CYGWIN) || defined(__HPUX) || defined(__IRIX) || defined(__SOLARIS) || defined(__OSF) || defined(__FREEBSD)

  signal(SIGHUP,(void(*)(int))ReloadConfig);

#else

  signal(SIGHUP,ReloadConfig);

#endif

  return(SUCCESS);
  }  /* END ReloadConfig() */

/* END OServer.c */