OW_Platform.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00037 #include "OW_config.h"
00038 #include "OW_Platform.hpp"
00039 #include "OW_ConfigOpts.hpp"
00040 #include "OW_Format.hpp"
00041 #include "OW_PidFile.hpp"
00042 #include "OW_ExceptionIds.hpp"
00043 #include "OW_PlatformSignal.hpp"
00044 #include "OW_ServiceEnvironmentIFC.hpp"
00045 #include "OW_Logger.hpp"
00046 
00047 #ifdef OW_NETWARE
00048 #include "OW_Condition.hpp"
00049 #include "OW_NonRecursiveMutex.hpp"
00050 #include "OW_NonRecursiveMutexLock.hpp"
00051 #endif
00052 
00053 extern "C"
00054 {
00055 #include <sys/types.h>
00056 #include <sys/stat.h>
00057 #include <errno.h>
00058 #if defined(OW_HAVE_GETOPT_H) && !defined(OW_GETOPT_AND_UNISTD_CONFLICT)
00059 #include <getopt.h>
00060 #else
00061 #include <stdlib.h> // for getopt on Solaris
00062 #endif
00063 #ifdef WIN32
00064 #include <process.h>
00065 #define getpid _getpid
00066 #else
00067 #include <unistd.h> // for getpid, getuid, etc.
00068 #endif
00069 #include <signal.h>
00070 #include <fcntl.h>
00071 #if defined (OW_HAVE_PWD_H)
00072 #include <pwd.h>
00073 #endif
00074 #if defined (OW_HAVE_SYS_RESOURCE_H)
00075 #include <sys/resource.h>
00076 #endif
00077 #if defined(OW_HAVE_GRP_H)
00078 #include <grp.h>
00079 #endif
00080 
00081 #ifdef OW_NETWARE
00082 #include <nks/vm.h>
00083 #include <nks/netware.h>
00084 #include <netware.h>
00085 #include <event.h>
00086 #include <library.h>
00087 #endif
00088 }
00089 #include <cstring>
00090 #include <cstdio>
00091 #include <iostream>
00092 
00093 using namespace std;
00094 
00095 namespace OW_NAMESPACE
00096 {
00097 
00098 using std::ostream;
00099 using std::endl;
00100 
00101 OW_DEFINE_EXCEPTION_WITH_ID(Daemon);
00102 
00103 namespace Platform
00104 {
00105 
00106 extern "C" {
00107 static void theSigHandler(int sig, siginfo_t* info, void* context);
00108 }
00109 
00110 namespace
00111 {
00112 const String COMPONENT_NAME("ow.owcimomd");
00113 
00114 const int DAEMONIZE_PIPE_TIMEOUT = 25;
00115 
00116 void handleSignal(int sig);
00117 void setupSigHandler(bool dbgFlg);
00118 
00119 UnnamedPipeRef plat_upipe;
00120 
00121 UnnamedPipeRef daemonize_upipe;
00122 
00123 char** g_argv = 0;
00124 
00125 #ifdef OW_NETWARE
00126 Condition g_shutdownCond;
00127 bool g_shutDown = false;
00128 NonRecursiveMutex g_shutdownGuard;
00129 void* WarnFuncRef = NULL;
00130 rtag_t EventRTag;
00131 event_handle_t DownEvent;
00132 bool FromEventHandler = false;
00133 #endif
00134 
00135 }
00136 
00138 void
00139 daemonInit( int argc, char* argv[] )
00140 {
00141    g_argv = argv;
00142 }
00147 void
00148 daemonize(bool dbgFlg, const String& daemonName, const ServiceEnvironmentIFCRef& env)
00149 {
00150 #ifndef WIN32
00151 #ifdef OW_NETWARE
00152    {
00153       NonRecursiveMutexLock l(g_shutdownGuard);
00154       g_shutDown = false;
00155    }
00156 #endif
00157    initDaemonizePipe();
00158 
00159    // If we're running as root and owcimomd.drop_root_privileges != "false", then try to switch users/groups to owcimomd/owcimomd
00160    if (geteuid() == 0 && !env->getConfigItem(ConfigOpts::DROP_ROOT_PRIVILEGES_opt, OW_DEFAULT_DROP_ROOT_PRIVILEGES).equalsIgnoreCase("false"))
00161    {
00162       const char OWCIMOMD_USER[] = "owcimomd";
00163       // dont need to worry about thread safety here, the threads won't start until later.
00164       struct passwd* owcimomdInfo = ::getpwnam(OWCIMOMD_USER);
00165       if (!owcimomdInfo)
00166       {
00167          OW_THROW_ERRNO_MSG(DaemonException, "Platform::daemonize(): getpwnam(\"owcimomd\")");
00168       }
00169       if (::setgid(owcimomdInfo->pw_gid) != 0)
00170       {
00171          OW_THROW_ERRNO_MSG(DaemonException, "Platform::daemonize(): setgid");
00172       }
00173       if (::initgroups(owcimomdInfo->pw_name, owcimomdInfo->pw_gid) != 0)
00174       {
00175          OW_THROW_ERRNO_MSG(DaemonException, "Platform::daemonize(): initgroups");
00176       }
00177       if (::setuid(owcimomdInfo->pw_uid) != 0)
00178       {
00179          OW_THROW_ERRNO_MSG(DaemonException, "Platform::daemonize(): setuid");
00180       }
00181    }
00182 
00183 
00184    int pid = -1;
00185 #if !defined(OW_NETWARE)
00186    String pidFile(env->getConfigItem(ConfigOpts::PIDFILE_opt, OW_DEFAULT_PIDFILE));
00187    pid = PidFile::checkPid(pidFile.c_str());
00188    // Is there already another instance of the cimom running?
00189    if (pid != -1)
00190    {
00191       OW_THROW(DaemonException,
00192          Format("Another instance of %1 is already running [%2]",
00193             daemonName, pid).c_str());
00194    }
00195 #endif
00196    if (!dbgFlg)
00197    {
00198 #if !defined(OW_NETWARE) && !defined(WIN32)
00199       pid = fork();
00200       switch (pid)
00201       {
00202          case 0:
00203             break;
00204          case -1:
00205             OW_THROW_ERRNO_MSG(DaemonException,
00206                "FAILED TO DETACH FROM THE TERMINAL - First fork");
00207          default:
00208             int status = DAEMONIZE_FAIL;
00209             if (daemonize_upipe->readInt(&status) < 1
00210                   || status != DAEMONIZE_SUCCESS)
00211             {
00212                cerr << "Error starting CIMOM.  Check the log files." << endl;
00213                _exit(1);
00214             }
00215             _exit(0); // exit the original process
00216       }
00217       if (setsid() < 0)               // shoudn't fail on linux
00218       {
00219          OW_THROW(DaemonException,
00220             "FAILED TO DETACH FROM THE TERMINAL - setsid failed");
00221       }
00222       pid = fork();
00223       switch (pid)
00224       {
00225          case 0:
00226             break;
00227          case -1:
00228             {
00229                // Save the error number, since the sendDaemonizeStatus function can cause it to change.
00230                int saved_errno = errno;
00231                sendDaemonizeStatus(DAEMONIZE_FAIL);
00232                // Restore the real error number.
00233                errno = saved_errno;
00234                OW_THROW_ERRNO_MSG(DaemonException,
00235                   "FAILED TO DETACH FROM THE TERMINAL - Second fork");
00236                exit(1);
00237             }
00238          default:
00239             _exit(0);
00240       }
00241 #endif
00242       chdir("/");
00243       close(0);
00244       close(1);
00245       close(2);
00246       open("/dev/null", O_RDONLY);
00247       open("/dev/null", O_WRONLY);
00248       dup(1);
00249    }
00250    else
00251    {
00252       pid = getpid();
00253    }
00254    umask(0077); // ensure all files we create are only accessible by us.
00255 #if !defined(OW_NETWARE)
00256    if (PidFile::writePid(pidFile.c_str()) == -1)
00257    {
00258       // Save the error number, since the sendDaemonizeStatus function can cause it to change.
00259       int saved_errno = errno;
00260       sendDaemonizeStatus(DAEMONIZE_FAIL);
00261       // Restore the real error number.
00262       errno = saved_errno;
00263       OW_THROW_ERRNO_MSG(DaemonException,
00264          Format("Failed to write the pid file (%1)", pidFile).c_str());
00265    }
00266 #endif
00267    OW_LOG_INFO(env->getLogger(COMPONENT_NAME), Format("Platform::daemonize() pid = %1", ::getpid()));
00268 #endif
00269    initSig();
00270 #ifndef WIN32
00271    setupSigHandler(dbgFlg);
00272 #endif
00273 
00274 #ifdef OW_HAVE_PTHREAD_ATFORK
00275    // this registers shutdownSig to be run in the child whenever a fork() happens. 
00276    // This will prevent a child process from writing to the signal pipe and shutting down the parent.
00277    ::pthread_atfork(NULL, NULL, &shutdownSig);
00278 #endif
00279 }
00281 int
00282 daemonShutdown(const String& daemonName, const ServiceEnvironmentIFCRef& env)
00283 {
00284 #ifndef WIN32
00285 #if defined(OW_NETWARE)
00286    (void)daemonName;
00287    {
00288       NonRecursiveMutexLock l(g_shutdownGuard);
00289       g_shutDown = true;
00290       g_shutdownCond.notifyAll();
00291       pthread_yield();
00292    }
00293    if(!FromEventHandler)
00294    {
00295       UnRegisterEventNotification(DownEvent);
00296    }
00297 #else
00298    String pidFile(env->getConfigItem(ConfigOpts::PIDFILE_opt, OW_DEFAULT_PIDFILE));
00299    PidFile::removePid(pidFile.c_str());
00300 #endif
00301 #endif
00302    shutdownSig();
00303    return 0;
00304 }
00305 
00307 void rerunDaemon()
00308 {
00309 #ifndef WIN32
00310 #ifdef OW_HAVE_PTHREAD_KILL_OTHER_THREADS_NP
00311    // do this, since it seems that on some distros (debian sarge for instance)
00312    // it doesn't happen when calling execv(), and it shouldn't hurt if it's
00313    // called twice.
00314    pthread_kill_other_threads_np();
00315 #endif
00316 
00317 #ifdef OW_DARWIN
00318    // On Darwin, execv() fails with a ENOTIMP if any threads are running.
00319    // The only way we have to really get rid of all the threads is to call fork() and exit() the parent.
00320    // Note that we don't do this on other platforms because fork() isn't safe to call from a signal handler, and isn't necessary.
00321    if (::fork() != 0)
00322    {
00323       _exit(1); // if fork fails or we're the parent, just exit.
00324    }
00325    // child continues.
00326 #endif
00327 
00328    // On Linux pthreads will kill off all the threads when we call
00329    // execv().  If we close all the fds, then that breaks pthreads and
00330    // execv() will just hang.
00331    // Instead set the close on exec flag so all file descriptors are closed
00332    // by the kernel when we evecv() and we won't leak them.
00333    rlimit rl;
00334    int i = sysconf(_SC_OPEN_MAX);
00335    if (getrlimit(RLIMIT_NOFILE, &rl) != -1)
00336    {
00337      if ( i < 0 )
00338      {
00339       i = rl.rlim_max;
00340      }
00341      else
00342      {
00343       i = std::min<int>(rl.rlim_max, i);
00344      }
00345    }
00346 
00347    struct flock lck;
00348    ::memset (&lck, '\0', sizeof (lck));
00349    lck.l_type = F_UNLCK;       // unlock
00350    lck.l_whence = 0;           // 0 offset for l_start
00351    lck.l_start = 0L;           // lock starts at BOF
00352    lck.l_len = 0L;             // extent is entire file
00353 
00354    while (i > 2)
00355    {
00356       // clear any file locks - this shouldn't technically be necessary, but it seems on some systems, even though we restart, the locks persist,
00357       // either because of bugs in the kernel or somehow things still hang around...
00358       ::fcntl(i, F_SETLK, &lck);
00359 
00360       // set it for close on exec
00361       ::fcntl(i, F_SETFD, FD_CLOEXEC);
00362       i--;
00363    }
00364 
00365    // reset the signal mask, since that is inherited by an exec()'d process, and if
00366    // this was called from a signal handler, the signal being handled (e.g. SIGSEGV) will be blocked.
00367    // some platforms make macros for sigemptyset, so we can't use ::
00368    sigset_t emptymask;
00369    sigemptyset(&emptymask);
00370    ::sigprocmask(SIG_SETMASK, &emptymask, 0);
00371 #endif
00372 
00373    // This doesn't return. execv() will replace the current process with a
00374    // new copy of g_argv[0] (owcimomd).
00375    ::execv(g_argv[0], g_argv);
00376 
00377    // If we get here we're pretty much hosed.
00378    OW_THROW_ERRNO_MSG(DaemonException, "execv() failed");
00379 }
00380 
00382 void restartDaemon()
00383 {
00384 #ifdef WIN32
00385    rerunDaemon();
00386 #else
00387    ::kill(::getpid(), SIGHUP);
00388 #endif
00389 }
00390 
00391 #ifndef WIN32
00392 
00393 namespace
00394 {
00395 
00397 #if !defined(OW_HAVE_SIGHANDLER_T)
00398 typedef void (*sighandler_t)(int);
00399 #endif
00400 
00401 void
00402 handleSignalAux(int sig, sighandler_t handler)
00403 {
00404    struct sigaction temp;
00405    memset(&temp, '\0', sizeof(temp));
00406    sigaction(sig, 0, &temp);
00407    temp.sa_handler = handler;
00408    sigemptyset(&temp.sa_mask);
00409    /* Here's a note from the glibc documentation:
00410     * When you don't specify with `sigaction' or `siginterrupt' what a
00411     * particular handler should do, it uses a default choice.  The default
00412     * choice in the GNU library depends on the feature test macros you have
00413     * defined.  If you define `_BSD_SOURCE' or `_GNU_SOURCE' before calling
00414     * `signal', the default is to resume primitives; otherwise, the default
00415     * is to make them fail with `EINTR'.  (The library contains alternate
00416     * versions of the `signal' function, and the feature test macros
00417     * determine which one you really call.)
00418     *
00419     * We want the EINTR behavior, so we can cancel threads and shutdown
00420     * or restart if the occasion arises, so we set flags to 0.
00421     *
00422     * This also clears the SA_SIGINFO flag so that the sa_handler member
00423     * may be safely used.
00424     */
00425    temp.sa_flags = 0;
00426    sigaction(sig, &temp, NULL);
00427 }
00428 
00429 // This typedef is not required to be defined anywhere in the header files,
00430 // but POSIX does show the signature of the function.
00431 // See http://www.opengroup.org/onlinepubs/009695399/functions/sigaction.html
00432 typedef void (*full_sighandler_t)(int,siginfo_t*,void*);
00433 
00434 // A signal handler installer for a full sigaction handler.  This is
00435 // different from the normal sighandler type only by the flags in the
00436 // handler and the field used in the sigaction struct
00437 // (sa_sigaction/sa_handler).
00438 void
00439 handleSignalAux(int sig, full_sighandler_t handler)
00440 {
00441    struct sigaction temp;
00442    memset(&temp, '\0', sizeof(temp));
00443    sigaction(sig, 0, &temp);
00444    temp.sa_sigaction = handler;
00445    sigemptyset(&temp.sa_mask);
00446    /* Here's a note from the glibc documentation:
00447     * When you don't specify with `sigaction' or `siginterrupt' what a
00448     * particular handler should do, it uses a default choice.  The default
00449     * choice in the GNU library depends on the feature test macros you have
00450     * defined.  If you define `_BSD_SOURCE' or `_GNU_SOURCE' before calling
00451     * `signal', the default is to resume primitives; otherwise, the default
00452     * is to make them fail with `EINTR'.  (The library contains alternate
00453     * versions of the `signal' function, and the feature test macros
00454     * determine which one you really call.)
00455     *
00456     * We want the EINTR behavior, so we can cancel threads and shutdown
00457     * or restart if the occasion arises, so we set flags to 0.
00458     *
00459     * We also want to use the sa_sigaction field, so we set SA_SIGINFO flag.
00460     */
00461    temp.sa_flags = SA_SIGINFO;
00462    sigaction(sig, &temp, NULL);
00463 }
00464 
00465 void
00466 handleSignal(int sig)
00467 {
00468    handleSignalAux(sig, theSigHandler);
00469 }
00470 void
00471 ignoreSignal(int sig)
00472 {
00473    handleSignalAux(sig, SIG_IGN);
00474 }
00475 
00476 } // end unnamed namespace
00477 
00478 #endif
00479 
00481 extern "C" {
00482 static void
00483 theSigHandler(int sig, siginfo_t* info, void* context)
00484 {
00485    int savedErrno = errno;
00486    try
00487    {
00488       Signal::SignalInformation extractedSignal;
00489       if( info )
00490       {
00491          Signal::extractSignalInformation( *info, extractedSignal );
00492       }
00493 
00494       switch (sig)
00495       {
00496          case SIGTERM:
00497          case SIGINT:
00498 #if defined(OW_NETWARE)
00499          case SIGABRT:
00500 #endif
00501             extractedSignal.signalAction = SHUTDOWN;
00502             pushSig(extractedSignal);
00503             break;
00504 #ifndef OW_WIN32
00505          case SIGHUP:
00506             extractedSignal.signalAction = REINIT;
00507             pushSig(extractedSignal);
00508             break;
00509 #endif
00510       }
00511    }
00512    catch (...) // can't let exceptions escape from here or we'll segfault.
00513    {
00514    }
00515    errno = savedErrno;
00516 
00517 }
00518 
00519 #ifndef WIN32
00520 
00521 static void
00522 fatalSigHandler(int sig, siginfo_t* info, void* context)
00523 {
00524    // we can't do much of *anything* besides restart here, since whatever caused the signal has left us in an unpredictable state,
00525    // it's unknown what could or could not work, not to mention that there are hardly any signal safe functions we could call.
00526    Platform::rerunDaemon();
00527 }
00528 
00529 #ifdef OW_NETWARE
00530 static void
00531 netwareExitHandler(void*)
00532 {
00533    theSigHandler(SIGTERM);
00534    pthread_yield();
00535    NonRecursiveMutexLock l(g_shutdownGuard);
00536    while(!g_shutDown)
00537    {
00538       g_shutdownCond.wait(l);
00539    }
00540 }
00541 
00542 static int
00543 netwareShutDownEventHandler(void*,
00544    void*, void*)
00545 {
00546    FromEventHandler = true;
00547    theSigHandler(SIGTERM);
00548    pthread_yield();
00549    NonRecursiveMutexLock l(g_shutdownGuard);
00550    while(!g_shutDown)
00551    {
00552       g_shutdownCond.wait(l);
00553    }
00554    return 0;
00555 }
00556 #endif
00557 
00558 #endif
00559 } // extern "C"
00560 #ifndef WIN32
00561 
00562 namespace
00563 {
00565 void
00566 setupSigHandler(bool dbgFlg)
00567 {
00568    /* Here's a note from the glibc documentation about signal():
00569     *Compatibility Note:* A problem encountered when working with the
00570     `signal' function is that it has different semantics on BSD and SVID
00571     systems.  The difference is that on SVID systems the signal handler is
00572     deinstalled after signal delivery.  On BSD systems the handler must be
00573     explicitly deinstalled.  In the GNU C Library we use the BSD version by
00574     default.  To use the SVID version you can either use the function
00575     `sysv_signal' (see below) or use the `_XOPEN_SOURCE' feature select
00576     macro ( Feature Test Macros).  In general, use of these
00577     functions should be avoided because of compatibility problems.  It is
00578     better to use `sigaction' if it is available since the results are much
00579     more reliable.
00580     We avoid using signal and use sigaction instead.
00581     */
00582    if (dbgFlg)
00583    {
00584       handleSignal(SIGINT);
00585    }
00586    else
00587    {
00588       ignoreSignal(SIGINT);
00589    }
00590    handleSignal(SIGTERM);
00591    handleSignal(SIGHUP);
00592 // handleSignal(SIGUSR2);
00593 
00594 // The thread code uses SIGUSR1 to implement cooperative cancellation, since
00595 // sending a signal can wake up a blocked system call.
00596 // handleSignal(SIGUSR1);
00597 
00598    ignoreSignal(SIGTTIN);
00599    ignoreSignal(SIGTTOU);
00600    ignoreSignal(SIGTSTP);
00601 #ifdef SIGPOLL
00602    ignoreSignal(SIGPOLL);
00603 #endif
00604 #ifdef SIGIO
00605    ignoreSignal(SIGIO);
00606 #endif
00607    ignoreSignal(SIGPIPE);
00608    // ?
00609 #ifdef SIGIOT // NetWare doesn't have this signal
00610    ignoreSignal(SIGIOT);
00611 #endif
00612    ignoreSignal(SIGCONT);
00613 #ifdef SIGURG // NetWare doesn't have this signal
00614    ignoreSignal(SIGURG);
00615 #endif
00616 #ifdef SIGXCPU // NetWare doesn't have this signal
00617    ignoreSignal(SIGXCPU);
00618 #endif
00619 #ifdef SIGXFSZ // NetWare doesn't have this signal
00620    ignoreSignal(SIGXFSZ);
00621 #endif
00622 #ifdef SIGVTALRM // NetWare doesn't have this signal
00623    ignoreSignal(SIGVTALRM);
00624 #endif
00625 #ifdef SIGPROF // NetWare doesn't have this signal
00626    ignoreSignal(SIGPROF);
00627 #endif
00628 #ifdef SIGPWR // FreeBSD doesn't have SIGPWR
00629    ignoreSignal(SIGPWR);
00630 #endif
00631 
00632    //handleSignal(SIGALRM);
00633    //handleSignal(SIGSTKFLT);
00634 
00635 #ifdef OW_NETWARE
00636    int rv;
00637    if ((rv = NXVmRegisterExitHandler(netwareExitHandler, 0) != 0))
00638    {
00639       OW_THROW(DaemonException,
00640          Format("FAILED TO REGISTER EXIT HANDLER "
00641          "NXVmRegisterExitHandler returned %1", rv).c_str());
00642    }
00643    EventRTag = AllocateResourceTag(getnlmhandle(), "Server down event",
00644       EventSignature);
00645    if(!EventRTag)
00646    {
00647       OW_THROW(DaemonException, "AllocationResourceTag FAILED");
00648    }
00649    NX_WRAP_INTERFACE((void*)netwareShutDownEventHandler, 3, &WarnFuncRef);
00650    DownEvent = RegisterForEventNotification(EventRTag,
00651       EVENT_DOWN_SERVER | EVENT_CONSUMER_MT_SAFE,
00652       EVENT_PRIORITY_APPLICATION, (Warn_t)WarnFuncRef, (Report_t)0, 0);
00653    if(!DownEvent)
00654    {
00655       OW_THROW(DaemonException, "FAILED to register for shutdown event");
00656    }
00657 #endif
00658 }
00659 
00660 } // end unnamed namespace
00661 
00663 void installFatalSignalHandlers()
00664 {
00665    handleSignalAux(SIGABRT, fatalSigHandler);
00666 
00667    handleSignalAux(SIGILL, fatalSigHandler);
00668 #ifdef SIGBUS // NetWare doesn't have this signal
00669    handleSignalAux(SIGBUS, fatalSigHandler);
00670 #endif
00671    handleSignalAux(SIGSEGV, fatalSigHandler);
00672    handleSignalAux(SIGFPE, fatalSigHandler);
00673 }
00674 
00676 void removeFatalSignalHandlers()
00677 {
00678    handleSignalAux(SIGABRT, SIG_DFL);
00679 
00680    handleSignalAux(SIGILL, SIG_DFL);
00681 #ifdef SIGBUS // NetWare doesn't have this signal
00682    handleSignalAux(SIGBUS, SIG_DFL);
00683 #endif
00684    handleSignalAux(SIGSEGV, SIG_DFL);
00685    handleSignalAux(SIGFPE, SIG_DFL);
00686 }
00687 #else // WIN32
00688 
00689 BOOL WINAPI CtrlHandlerRoutine(DWORD dwCtrlType)
00690 {
00691    theSigHandler(SIGTERM, 0, 0);
00692    return TRUE;
00693 }
00694 
00695 void installFatalSignalHandlers()
00696 {
00697    ::SetConsoleCtrlHandler(CtrlHandlerRoutine, TRUE);
00698 }
00699 
00700 void removeFatalSignalHandlers()
00701 {
00702    ::SetConsoleCtrlHandler(CtrlHandlerRoutine, FALSE);
00703 }
00704 
00705 #endif // WIN32
00706 
00708 void initDaemonizePipe()
00709 {
00710    daemonize_upipe = UnnamedPipe::createUnnamedPipe();
00711    daemonize_upipe->setTimeouts(DAEMONIZE_PIPE_TIMEOUT);
00712 }
00713 
00715 void sendDaemonizeStatus(int status)
00716 {
00717    if (daemonize_upipe)
00718    {
00719       daemonize_upipe->writeInt(status);
00720    }
00721 }
00722 
00724 void initSig()
00725 {
00726    plat_upipe = UnnamedPipe::createUnnamedPipe();
00727    plat_upipe->setBlocking(UnnamedPipe::E_NONBLOCKING);
00728 }
00730 void pushSig(const Signal::SignalInformation& sig)
00731 {
00732    if (plat_upipe)
00733    {
00734       Signal::flattenSignalInformation(sig, plat_upipe);
00735    }
00736    // don't throw from this function, it may cause a segfault or deadlock.
00737 }
00739 int popSig(Signal::SignalInformation& sig)
00740 {
00741    int tmp = -2;
00742    if (plat_upipe)
00743    {
00744       if( !Signal::unflattenSignalInformation(sig, plat_upipe) )
00745       {
00746          return -1;
00747       }
00748       tmp = sig.signalAction;
00749    }
00750    return tmp;
00751 }
00753 void shutdownSig()
00754 {
00755    plat_upipe = 0;
00756 }
00757 
00759 SelectableIFCRef getSigSelectable()
00760 {
00761    return plat_upipe;
00762 }
00763 
00764 
00766 
00767 } // end namespace Platform
00768 } // end namespace OW_NAMESPACE
00769 

Generated on Thu Feb 9 08:48:08 2006 for openwbem by  doxygen 1.4.6