5

I am writing a small program which has a heartbeat process and an echo process. I implemented this with a multiprocessing library, but it doesn't seem to work.

from multiprocessing import Process
import os
import time

def ticking():
    while True:
        time.sleep(1)
        print 'ticking'

def echo():
    while True:
        a = raw_input('please type something')
        print 'echo: ' + a

if __name__ == '__main__':
    p = Process(target=ticking, args=())
    p.start()
    p.join()

    p = Process(target=echo, args=())
    p.start()
    p.join()
alvinzoo
  • 493
  • 2
  • 8
  • 17
  • 1
    The [python-daemon](https://pypi.python.org/pypi/python-daemon/) library is a handy package to create daemons easily, by the way. – Martin Tournoij Mar 16 '16 at 10:26
  • Agreed, `multiprocessing` isn't the right tool to implement a daemon. Generally you want to use the double-forking idiom for a Unix daemon, so just use the library Carpetsmoker linked. – Sven Marnach Mar 16 '16 at 10:28
  • @Carpetsmoker Thanks, will try :) – alvinzoo Mar 16 '16 at 11:38

2 Answers2

5

You create a process that will run forever and join() to it. The second process will never get created, because the join() will stall your main process forever.

If this is how you want to proceed, then you should for example first create both processes and then join them:

if __name__ == '__main__':
    p1 = Process(target=ticking, args=())
    p1.start()

    p2 = Process(target=echo, args=())
    p2.start()

    p1.join()
    p2.join()
Ilja Everilä
  • 50,538
  • 7
  • 126
  • 127
  • Documentation for [`join()`](https://docs.python.org/3.5/library/multiprocessing.html#multiprocessing.Process.join). "the method blocks until the process whose join() method is called terminates." – Chuck Mar 16 '16 at 10:25
  • Yeah, but the result is the same :P – Ilja Everilä Mar 16 '16 at 10:27
2

For create a daemon you can use this function:

def daemonize():
    """UNIX double fork mechanism."""
    try:
        pid = os.fork()
        if pid > 0:
            # exit first parent
            sys.exit(0)
    except OSError as err:
        sys.stderr.write('_Fork #1 failed: {0}\n'.format(err))
        sys.exit(1)
    # decouple from parent environment
    os.chdir('/')
    os.setsid()
    os.umask(0)
    # do second fork
    try:
        pid = os.fork()
        if pid > 0:
            # exit from second parent
            sys.exit(0)
    except OSError as err:
        sys.stderr.write('_Fork #2 failed: {0}\n'.format(err))
        sys.exit(1)
    # redirect standard file descriptors
    sys.stdout.flush()
    sys.stderr.flush()
    si = open(os.devnull, 'r')
    so = open(os.devnull, 'w')
    se = open(os.devnull, 'w')
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())
Ivan Kolesnikov
  • 1,787
  • 1
  • 29
  • 45
  • I undestood why to do `os.setsid()` after reading [this](https://stackoverflow.com/a/6553076/1317018). But why to do **(1)** `os.chdir('/')` **(2)** `os.umask(0)` and **(3)** that file descriptor stuff? What if I dont do some of them? Also can we do similar with python [`multiprocessing.Process`](https://docs.python.org/3.4/library/multiprocessing.html)? – Mahesha999 Aug 31 '18 at 08:16
  • 2
    @Mahesha999 1. We need to change the working directory for a safe place. For example, directory from which the application will be run may be unmount in the future. The root directory is the best way. 2. umask(0) gives full access (-rw-rw-rw-) to the files which will created by the daemon. 3. We close file descriptors as the daemon disconnected from the terminal and shouldn't send any data via pipes. For that we open /dev/null and change the daemon's file discriptors to the /dev/null descriptors. – Ivan Kolesnikov Aug 31 '18 at 08:59
  • 1
    @Mahesha999 We do all these things as these are rules of creating daemon process: http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html I showed the way how to transform an application to the daemon via one function. This method only depends on sys and os modules. Also exist other ways to create unix daemon in python, it's only one of them. – Ivan Kolesnikov Aug 31 '18 at 08:59