daemon.cxx

Go to the documentation of this file.
00001 // @(#)root/rpdutils:$Id: daemon.cxx 28598 2009-05-13 12:52:40Z rdm $
00002 // Author: Fons Rademakers   11/08/97
00003 // Modifified: Gerardo Ganis 8/04/2003
00004 
00005 /*************************************************************************
00006  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00007  * All rights reserved.                                                  *
00008  *                                                                       *
00009  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00010  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00011  *************************************************************************/
00012 
00013 //////////////////////////////////////////////////////////////////////////
00014 //                                                                      //
00015 // DaemonStart                                                          //
00016 //                                                                      //
00017 // Detach a daemon process from login session context.                  //
00018 //                                                                      //
00019 //////////////////////////////////////////////////////////////////////////
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <signal.h>
00025 #include <sys/stat.h>
00026 #include <sys/param.h>
00027 #if defined(__sun) || defined(__sgi)
00028 #  include <fcntl.h>
00029 #endif
00030 
00031 #ifdef SIGTSTP
00032 #include <sys/file.h>
00033 #include <sys/ioctl.h>
00034 #include <sys/wait.h>
00035 #endif
00036 
00037 #ifndef NOFILE
00038 #   define NOFILE 0
00039 #endif
00040 
00041 #if defined(__hpux)
00042 #define USE_SIGCHLD
00043 #endif
00044 
00045 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
00046 #define USE_SIGCHLD
00047 #define SIGCLD SIGCHLD
00048 #endif
00049 
00050 #if defined(linux) || defined(__hpux) || defined(__sun) || defined(__sgi) || \
00051     defined(_AIX) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
00052     defined(__APPLE__) || defined(__MACH__) || \
00053     (defined(__CYGWIN__) && defined(__GNUC__))
00054 #define USE_SETSID
00055 #endif
00056 
00057 
00058 #include "rpdp.h"
00059 
00060 extern int gDebug;
00061 
00062 namespace ROOT {
00063 
00064 extern ErrorHandler_t gErrSys;
00065 
00066 #if defined(USE_SIGCHLD)
00067 //______________________________________________________________________________
00068 static void SigChild(int)
00069 {
00070    int         pid;
00071 #if defined(__hpux) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
00072     defined(__APPLE__)
00073    int status;
00074 #else
00075    union wait  status;
00076 #endif
00077 
00078    while ((pid = wait3(&status, WNOHANG, 0)) > 0)
00079       ;
00080 }
00081 #endif
00082 
00083 //______________________________________________________________________________
00084 void DaemonStart(int ignsigcld, int fdkeep, EService service)
00085 {
00086    // Detach a daemon process from login session context.
00087 
00088    // If we were started by init (process 1) from the /etc/inittab file
00089    // there's no need to detach.
00090    // This test is unreliable due to an unavoidable ambiguity
00091    // if the process is started by some other process and orphaned
00092    // (i.e. if the parent process terminates before we are started).
00093 
00094    int fd;
00095 
00096 #if !(defined(__CYGWIN__) && defined(__GNUC__))
00097    if (getppid() == 1) {
00098       if (service == kROOTD) printf ("ROOTD_PID=%ld\n", (long) getpid());
00099       goto out;
00100    }
00101 #endif
00102 
00103    // Ignore the terminal stop signals (BSD).
00104 
00105 #ifdef SIGTTOU
00106    signal(SIGTTOU, SIG_IGN);
00107 #endif
00108 #ifdef SIGTTIN
00109    signal(SIGTTIN, SIG_IGN);
00110 #endif
00111 #ifdef SIGTSTP
00112    signal(SIGTSTP, SIG_IGN);
00113 #endif
00114 
00115    // If we were not started in the background, fork and let the parent
00116    // exit. This also guarantees the first child is not a process
00117    // group leader.
00118 
00119    int childpid;
00120    if ((childpid = fork()) < 0) {
00121       if (service == kROOTD) fprintf(stderr, "DaemonStart: can't fork first child\n");
00122       Error(gErrSys,kErrFatal, "DaemonStart: can't fork first child");
00123    } else if (childpid > 0) {
00124 #ifdef SIGTSTP
00125       if (service == kROOTD) printf("ROOTD_PID=%d\n", childpid);
00126 #endif
00127       exit(0);    // parent
00128    } else {
00129       if (gDebug > 2)
00130          ErrorInfo("DaemonStart: this is the child thread ... socket is: %d",fdkeep);
00131    }
00132 
00133    // First child process...
00134 
00135    // Disassociate from controlling terminal and process group.
00136    // Ensure the process can't reacquire a new controlling terminal.
00137 
00138 #ifdef SIGTSTP
00139 
00140 #ifdef USE_SETSID
00141    if (setsid() == -1) {
00142 #else
00143    if (setpgrp(0, getpid()) == -1) {
00144 #endif
00145       if (service == kROOTD)
00146          fprintf(stderr, "DaemonStart: can't change process group\n");
00147       Error(gErrSys,kErrFatal, "DaemonStart: can't change process group");
00148    }
00149 
00150    if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
00151 #if !defined(__hpux) && !defined(__sun) && \
00152     !(defined(__CYGWIN__) && defined(__GNUC__))
00153       ioctl(fd, TIOCNOTTY, 0);       // loose controlling tty
00154 #endif
00155       close(fd);
00156    }
00157 
00158 #else
00159 
00160    if (setpgrp() == -1) {
00161       if (service == kROOTD)
00162          fprintf(stderr,"DaemonStart: can't change process group\n");
00163       Error(gErrSys,kErrFatal, "DaemonStart: can't change process group");
00164    }
00165 
00166    signal(SIGHUP, SIG_IGN);    // immune from pgrp leader death
00167 
00168    if ((childpid = fork()) < 0) {
00169       if (service == kROOTD)
00170          fprintf(stderr,     "DaemonStart: can't fork second child\n");
00171       Error(gErrSys,kErrFatal, "DaemonStart: can't fork second child");
00172    } else if (childpid > 0) {
00173       if (service == kROOTD) printf("ROOTD_PID=%d (2nd fork)\n", childpid);
00174       exit(0);    // first child
00175    }
00176 
00177 #endif
00178 out:
00179    // Close any open file descriptors
00180    for (fd = 0; fd < NOFILE; fd++) {
00181       if ((fd != fdkeep) || (service == kPROOFD)) close(fd);
00182    }
00183 
00184    ResetErrno();   // probably got set to EBADF from a close
00185 
00186    // Move current directory to root, make sure we aren't on a mounted
00187    // file system.
00188 
00189    if (chdir("/") == -1)
00190       fprintf(stderr, "DaemonStart: cannot chdir to /\n");
00191 
00192    // Clear any inherited file mode creation mask
00193 
00194    umask(0);
00195 
00196    // See if the caller isn't interested in the exit status of its
00197    // children and doesn't want to have them become zombies and
00198    // clog up the system.
00199    // With SysV all we need to do is ignore the signal.
00200    // With BSD, however, we have to catch each signal
00201    // and execute the wait3() system call.
00202 
00203    if (ignsigcld) {
00204 #ifdef USE_SIGCHLD
00205       signal(SIGCLD, SigChild);
00206 #else
00207 #if defined(__alpha) && !defined(linux)
00208       struct sigaction oldsigact, sigact;
00209       sigact.sa_handler = SIG_IGN;
00210       sigemptyset(&sigact.sa_mask);
00211       sigact.sa_flags = SA_NOCLDWAIT;
00212       sigaction(SIGCHLD, &sigact, &oldsigact);
00213 #elif defined(__sun)
00214       sigignore(SIGCHLD);
00215 #else
00216       signal(SIGCLD, SIG_IGN);
00217 #endif
00218 #endif
00219    }
00220 }
00221 
00222 } // namespace ROOT
00223 

Generated on Tue Jul 5 14:46:13 2011 for ROOT_528-00b_version by  doxygen 1.5.1