⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svcproc.cxx

📁 opal的ptlib c++源程序 可以从官方网站上下载
💻 CXX
📖 第 1 页 / 共 2 页
字号:
            case -1 :
              break;
            case 0 :
              PFile::Remove(pidfilename);
              return 0;
            case 1 :
              return 2;
          }
        }
        else
          return 2;
    }

    cout << "Could not stop process " << pid <<
            " - " << strerror(errno) << endl;
    return 1;
  }

  // Set the gid we are running under
  if (args.HasOption('g')) {
    PString gidstr = args.GetOptionString('g');
    if (!SetGroupName(gidstr)) {
      cout << "Could not set GID to \"" << gidstr << "\" - " << strerror(errno) << endl;
      return 1;
    }
  }

  // Set the uid we are running under
  if (args.HasOption('u')) {
    PString uidstr = args.GetOptionString('u');
    if (!SetUserName(uidstr)) {
      cout << "Could not set UID to \"" << uidstr << "\" - " << strerror(errno) << endl;
      return 1;
    }
  }

  PBoolean helpAndExit = PFalse;

  // if displaying help, then do it
  if (args.HasOption('h')) 
    helpAndExit = PTrue;
  else if (!args.HasOption('d') && !args.HasOption('x')) {
    cout << "error: must specify one of -v, -h, -t, -k, -d or -x" << endl;
    helpAndExit = PTrue;
  }

  // set flag for console messages
  if (args.HasOption('c')) {
    systemLogFileName = '-';
    debugMode = PTrue;
  }

  if (args.HasOption('l')) {
    systemLogFileName = args.GetOptionString('l');
    if (systemLogFileName.IsEmpty()) {
      cout << "error: must specify file name for -l" << endl;
      helpAndExit = PTrue;
    }
    else if (PDirectory::Exists(systemLogFileName))
      systemLogFileName = PDirectory(systemLogFileName) + PProcess::Current().GetFile().GetFileName() + ".log";
  }

  if (helpAndExit) {
    cout << "usage: [-c] -v|-d|-h|-x\n"
            "  -h --help           output this help message and exit\n"
            "  -v --version        display version information and exit\n"
#if !defined(BE_THREADS) && !defined(P_RTEMS)
            "  -d --daemon         run as a daemon\n"
#endif
            "  -u --uid uid        set user id to run as\n"
            "  -g --gid gid        set group id to run as\n"
            "  -p --pid-file       name or directory for pid file\n"
            "  -t --terminate      orderly terminate process in pid file\n"
            "  -k --kill           preemptively kill process in pid file\n"
            "  -s --status         check to see if daemon is running\n"
            "  -c --console        output messages to stdout rather than syslog\n"
            "  -l --log-file file  output messages to file or directory instead of syslog\n"
            "  -x --execute        execute as a normal program\n"
            "  -i --ini-file       set the ini file to use, may be explicit file or\n"
            "                      a ':' separated set of directories to search.\n"
            "  -H --handlemax n    set maximum number of file handles (set before uid/gid)\n"
#ifdef P_LINUX
            "  -C --core-size      set the maximum core file size\n"
#endif
         << endl;
    return 0;
  }

  // open the system logger for this program
  if (systemLogFileName.IsEmpty())
    openlog((char *)(const char *)GetName(), LOG_PID, LOG_DAEMON);
  else if (systemLogFileName == "-")
    cout << "All output for " << GetName() << " is to console." << endl;
  else {
    ofstream logfile(systemLogFileName, ios::app);
    if (!logfile.is_open()) {
      cout << "Could not open log file \"" << systemLogFileName << "\""
              " - " << strerror(errno) << endl;
      return 1;
    }
  }
  PSYSTEMLOG(StdError, "Starting service process \"" << GetName() << "\" v" << GetVersion(PTrue));

  if (args.HasOption('i'))
    SetConfigurationPath(args.GetOptionString('i'));

  if (args.HasOption('H')) {
    int uid = geteuid();
    seteuid(getuid()); // Switch back to starting uid for next call
    SetMaxHandles(args.GetOptionString('H').AsInteger());
    seteuid(uid);
  }

  // set the core file size
  if (args.HasOption('C')) {
#ifdef P_LINUX
    struct rlimit rlim;
    if (getrlimit(RLIMIT_CORE, &rlim) != 0) 
      cout << "Could not get current core file size : error = " << errno << endl;
    else {
      int uid = geteuid();
      seteuid(getuid()); // Switch back to starting uid for next call
      int v = args.GetOptionString('C').AsInteger();
      rlim.rlim_cur = v;
      if (setrlimit(RLIMIT_CORE, &rlim) != 0) 
        cout << "Could not set current core file size to " << v << " : error = " << errno << endl;
      else {
        getrlimit(RLIMIT_CORE, &rlim);
        cout << "Core file size set to " << rlim.rlim_cur << "/" << rlim.rlim_max << endl;
      }
      seteuid(uid);
    }
#endif
  }

#if !defined(BE_THREADS) && !defined(P_RTEMS)
  if (!args.HasOption('d'))
    return -1;

  // Run as a daemon, ie fork

  if (!pidfilename) {
    ifstream pidfile(pidfilename);
    if (pidfile.is_open()) {
      pid_t pid;
      pidfile >> pid;
      if (pid != 0 && kill(pid, 0) == 0) {
        cout << "Already have daemon running with pid " << pid << endl;
        return 2;
      }
    }
  }

  // Need to get rid of the config write thread before fork, as on
  // pthreads platforms the forked process does not have the thread
  CommonDestruct();

  pid_t pid = fork();
  switch (pid) {
    case 0 : // The forked process
      break;

    case -1 : // Failed
      cout << "Fork failed creating daemon process." << endl;
      return 1;

    default : // Parent process
      cout << "Daemon started with pid " << pid << endl;
      if (!pidfilename) {
        // Write out the child pid to magic file in /var/run (at least for linux)
        ofstream pidfile(pidfilename);
        if (pidfile.is_open())
          pidfile << pid;
        else
          cout << "Could not write pid to file \"" << pidfilename << "\""
                  " - " << strerror(errno) << endl;
      }
      return 0;
  }

  // Set ourselves as out own process group so we don't get signals
  // from our parent's terminal (hopefully!)
  PSETPGRP();

  CommonConstruct();

  pidFileToRemove = pidfilename;

  // Only if we are running in the background as a daemon, we intercept
  // the core dumping signals so get a message in the log file.
  signal(SIGSEGV, PXSignalHandler);
  signal(SIGFPE, PXSignalHandler);
  signal(SIGBUS, PXSignalHandler);

  // Also if in background, don't want to get blocked on input from stdin
  ::close(STDIN_FILENO);

#endif // !BE_THREADS && !P_RTEMS
#endif // !P_VXWORKS
  return -1;
}

int PServiceProcess::_main(void *)
{
  if ((terminationValue = InitialiseService()) < 0) {
    // Make sure housekeeping thread is going so signals are handled.
    SignalTimerChange();

    terminationValue = 1;
    if (OnStart()) {
      terminationValue = 0;
      Main();
      Terminate();
    }
  }

  return terminationValue;
}


PBoolean PServiceProcess::OnPause()
{
  return PTrue;
}

void PServiceProcess::OnContinue()
{
}

void PServiceProcess::OnStop()
{
}


void PServiceProcess::Terminate()
{
  if (isTerminating) {
    // If we are the process itself and another thread is terminating us,
    // just stop and wait forever for us to go away
    if (PThread::Current() == this)
      Sleep(PMaxTimeInterval);
    PSYSTEMLOG(Error, "Nested call to process termination!");
    return;
  }

  isTerminating = PTrue;

  PSYSTEMLOG(Warning, "Stopping service process \"" << GetName() << "\" v" << GetVersion(PTrue));

  // Avoid strange errors caused by threads (and the process itself!) being destoyed 
  // before they have EVER been scheduled
  Yield();

  // Do the services stop code
  OnStop();

#ifndef P_VXWORKS
  // close the system log
  if (systemLogFileName.IsEmpty())
    closelog();
#endif // !P_VXWORKS

  // Now end the program
  exit(terminationValue);
}

void PServiceProcess::PXOnAsyncSignal(int sig)
{
  const char * sigmsg;

  // Override the default behavious for these signals as that just
  // summarily exits the program. Allow PXOnSignal() to do orderly exit.

  switch (sig) {
    case SIGINT :
    case SIGTERM :
    case SIGHUP :
      return;

    case SIGSEGV :
      sigmsg = "segmentation fault (SIGSEGV)";
      break;

    case SIGFPE :
      sigmsg = "floating point exception (SIGFPE)";
      break;

#ifndef __BEOS__ // In BeOS, SIGBUS is the same value as SIGSEGV
    case SIGBUS :
      sigmsg = "bus error (SIGBUS)";
      break;
#endif
    default :
      PProcess::PXOnAsyncSignal(sig);
      return;
  }

  signal(SIGSEGV, SIG_DFL);
  signal(SIGFPE, SIG_DFL);
  signal(SIGBUS, SIG_DFL);

  static PBoolean inHandler = PFalse;
  if (inHandler) {
    raise(SIGQUIT); // Dump core
    _exit(-1); // Fail safe if raise() didn't dump core and exit
  }

  inHandler = PTrue;

#ifdef P_MAC_MPTHREADS
  unsigned tid = (unsigned)MPCurrentTaskID();
#elif defined(P_VXWORKS)
  unsigned tid = ::taskIdSelf();
#elif defined(BE_THREADS)
  thread_id tid = ::find_thread(NULL);
#else
  unsigned tid = (unsigned) pthread_self();
#endif
  PThread * thread_ptr = activeThreads.GetAt(tid);

  char msg[200];
  sprintf(msg, "\nCaught %s, thread_id=%u", sigmsg, tid);

  if (thread_ptr != NULL) {
    PString thread_name = thread_ptr->GetThreadName();
    if (thread_name.IsEmpty())
      sprintf(&msg[strlen(msg)], " obj_ptr=%p", thread_ptr);
    else {
      strcat(msg, " name=");
      strcat(msg, thread_name);
    }
  }

  strcat(msg, ", aborting.\n");

  if (systemLogFileName.IsEmpty()) {
#ifdef P_VXWORKS
  logMsg((char *)msg,0,0,0,0,0,0);
#else
    syslog(LOG_CRIT, msg); 
    closelog();
#endif // !P_VXWORKS
  }
  else {
#ifdef P_VXWORKS
    int fd = open(systemLogFileName, O_WRONLY|O_APPEND, FWRITE|FAPPEND);
#else
    int fd = open(systemLogFileName, O_WRONLY|O_APPEND);
#endif // !P_VXWORKS
    if (fd >= 0) {
      write(fd, msg, strlen(msg));
      close(fd);
    }
  }

  raise(SIGQUIT); // Dump core
  _exit(-1); // Fail safe if raise() didn't dump core and exit
}


void PServiceProcess::PXOnSignal(int sig)
{
  PProcess::PXOnSignal(sig);
  switch (sig) {
    case SIGINT :
    case SIGTERM :
      Terminate();
      break;

    case SIGUSR1 :
      OnPause();
      break;

    case SIGUSR2 :
      OnContinue();
      break;

#if 0
    case SIGHUP :
      if (currentLogLevel < PSystemLog::NumLogLevels-1) {
        currentLogLevel = (PSystemLog::Level)(currentLogLevel+1);
        PSystemLog s(PSystemLog::StdError);
        s << "Log level increased to " << PLevelName[currentLogLevel+1];
      }
      break;

#ifdef SIGWINCH
    case SIGWINCH :
      if (currentLogLevel > PSystemLog::Fatal) {
        currentLogLevel = (PSystemLog::Level)(currentLogLevel-1);
        PSystemLog s(PSystemLog::StdError);
        s << "Log level decreased to " << PLevelName[currentLogLevel+1];
      }
      break;
#endif
#endif
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -