[omniORB] Running a Server Object as Daemon

W. Eliot Kimber eliot@isogen.com
Thu, 13 Dec 2001 16:36:56 -0600


All,

I don't know if this code will be useful, but a search of the maillist
archive didn't reveal anything like this. And please tell me if there's
a easier way to do this.

I just wanted to be able to start our main server object as a daemon
under linux. Since I'm not a shell script hack, I did it all directly in
Python:

Here is the daemon startup module:

#!/usr/bin/python
#----------------------------------------------------------
#
# Server Daemon Process
#
#
#---------------------------------------------------------
"""
Linux Server Daemon

Usage:

bonnelld  [[start] [-n] -ORBInitRef
NameService=corbaname::{nameservername} -ORBpoa_iiop_name_port
{hostname} ]
          [stop]

   start
       Starts the daemon. You must provide the ORBInitRef and
ORBpoa_iiop_name_port parameters, where
       {nameservername} is the hostname or IP address of the name server
(e.g., "localhost" if the nameserver
       is running on the same machine as the Bonnell daemon), and
{hostname} is the hostname or IP address
       that the Bonnell server is running on.

       -n Do not run as a daemon but as a foreground process.

   stop
       Stops a running daemon. Note that the user that stops the process
must have the authority
       to kill the process.
          
"""

import ZODB
from ZODB import FileStorage

import os.path
import sys

if sys.platform[0] != "l":  # Lowercase "l" for linux
    print "This daemon only works under Linux"
    sys.exit(-1)

import daemon
import string

from bonnellcore import BonnellUtils
from bonnellcorba.BonnellServer import BonnellServer
from bonnellcore.BonnellServer import initDB

import CosNaming
from omniORB import CORBA

from zLOG import LOG, TRACE, DEBUG, BLATHER, INFO, PROBLEM, WARNING,
ERROR, PANIC

cwd = BonnellUtils.cwd(globals(), locals())

d = daemon.Daemon(cwd=cwd)

runAsDaemon = 1

cmd = "START"
if len(sys.argv) > 1:
    for opt in sys.argv[1:]:
        if opt == "-n":
            runAsDaemon = 0
            sys.argv.remove(opt)
        if string.upper(opt) in ("START", "STOP", "SHUTDOWN", "HALT"):
            cmd = string.upper(opt)
            sys.argv.remove(opt)
            
if cmd in ("STOP", "SHUTDOWN", "HALT"):
    if not d.isRunning():
        print "Daemon is not running, %s request ignored" % cmd
        sys.exit(0)
        
    LOG("bonnelld.%s" % __name__, TRACE, \
        "Attempting to kill daemon process")
    try:
        d.killMyself()
        print "Bonnell daemon killed"
        sys.exit(0)
    except daemon.KillFailedError, exc:
        print "Unable to kill process ID %s" % exc
        sys.exit(-1)

# Otherwise, just start up:
if runAsDaemon:
    try:
        LOG("bonnelld.%s" % __name__, TRACE, \
            "About to go into daemon mode")
        d.runAsDaemon()
        LOG("bonnelld.%s" % __name__, TRACE, \
            "Now running as a daemon, pid=%s" % os.getpid())
    except daemon.DaemonIsRunning:
        print "Daemon is already running, quiting"
        sys.exit(0)


dataFS = os.path.join(cwd, "data.fs")

LOG("bonnelld.%s" % __name__, TRACE, \
    "Got a data.fs file")

storage = ZODB.FileStorage.FileStorage(dataFS)
db = ZODB.DB(storage)
initDB(db)

#test CORBA objects
bServ = BonnellServer(storage)
LOG("bonnelld.%s" % __name__, TRACE, \
    "Got a bServ object")

bServObj = bServ._this()

orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)

LOG("bonnelld.%s" % __name__, TRACE, \
    "Got an ORB")
try:
    ns = orb.resolve_initial_references("NameService")
    ns = ns._narrow(CosNaming.NamingContext)

    LOG("bonnelld.%s" % __name__, TRACE, \
        "Got a naming service object")

    name = [CosNaming.NameComponent("BonnellServer", "")]

    ns.rebind(name, bServObj)

    LOG("bonnelld.%s" % __name__, TRACE, \
        "Starting orb.run()")

    orb.run()
except Exception, exc:
    LOG("bonnelld.%s" % __name__, TRACE, \
        "Got exception %s" % exc)
    if not runAsDaemon:
        import traceback
        trackback.print_exc()
# End of script
-- 

Here is the daemon module, which is generic:

#-------------------------------------------------------
#
# Daemon startup module.
#
# Based on code posted by Ben Caradoc-Davies <bmcd@es.co.nz>, June 1999
# to comp.lang.python.
#
#--------------------------------------------------------
import os
import sys

def fork_and_die():
    r = os.fork()
    if r == -1:
        raise OSError, "Couldn't fork()."
    elif r > 0:  # I'm the parent
        sys.exit(0)
    elif r < 0:
        raise OSError, "Something bizarre happened while trying to
fork()."
        # now only r = 0 (the child) survives.

class Daemon:
    """
    Turns the current Python process into a daemon running in the
background.

    Usage:

    Just create a Daemon object and call the runAsDaemon() method to go
into Daemon mode.

    Creates a file with the daemon's PID that can be used to kill this
process
    from a script and to prevent second instances from starting.
    """

    def __init__(self, umask=077, chdir="/", pidfile = None ):
        self.umask = umask
        self.chdir = chdir
        self.pdifile = pidfile


    def runAsDaemon(self):
        fork_and_die()
        os.setsid()
        fork_and_die()
        os.chdir(self.chdir)
        os.umask(self.umask)
        sys.stdin.close()
        sys.stdout.close()
        sys.stderr.close()
# End of module

. . . . . . . . . . . . . . . . . . . . . . . .

W. Eliot Kimber | Lead Brain

1016 La Posada Dr. | Suite 240 | Austin TX  78752
    T 512.656.4139 |  F 512.419.1860 | eliot@isogen.com

w w w . d a t a c h a n n e l . c o m