Às vezes eu escrevo programas.  Entre esse programas, alguns são daemons.
Que erro maldito!

Além da confusão com demônios, o que são daemons?

Daemons são os programas que rodam em background no sistema, não precisando de um terminal (console) anexado.  E qualquer tipo de programa pode ser um daemon, pra qualquer finalidade.

Em geral daemons seguem as seguintes regras pra se tornarem daemons:

  1. Mudar pro diretório raiz ("/").
  2. Realizar um fork().
  3. Finalizar o processo pai, ficando somente o filho, criado no fork().
  4. Realizar outro fork().
  5. Finalizar o primeiro processo filho, deixando somente o segundo, criado no segundo fork().

O segundo fork() é feito para garantir que o programa, através do segundo processo filho, seja "herdado" pelo processo init do sistema.

Em Python, sempre incluo uma função como essa:

   def Daemonize(self):
      """
      Fork to became a daemon.
      """
      
      if not self.isDaemon:
         try:
            self.run()
         except KeyboardInterrupt:
            sys.exit(0)
         return
      
      os.chdir("/")
      pid = os.fork()
      
      if (pid > 0):
         sys.exit(os.EX_OK)
      else:
         pid = os.fork()
         
         if (pid > 0):
            sys.exit(os.EX_OK)
         else:
            self.run()

Esse é parte de um método, mas poderia ser uma função.  A idéia é usar o getopt() para verificar as opções passadas e entrar no modo de daemon ou não, dependendo da opção passada, que modifica a variável booleana self.isDaemon.

Mas um dos meus programs começou a apresentar o seguinte erro:

helio@goosfraba:~$ connect_TSP.py ccn
IP already setup... skipping root access
Running as daemon
daemonized...
close failed in file object destructor:
IOError: [Errno 10] No child processes
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/apport_python_hook.py", line 66, in apport_excepthook
    from apport.fileutils import likely_packaged, get_recent_crashes
RuntimeError: sys.meta_path must be a list of import hooks

Original exception was:
IOError: [Errno 10] No child processes

Inicialmente achei que era problema no "apport" com meu programa, que usa python-expect.  Mesmo com tal erro, o programa funcionava perfeitamente em background, como daemon.  Várias fontes na Internet, principalmente no Launchpad, o sistema de bug report do Ubuntu, várias pessoas reclamavam de tal erro como sendo problema do apport.

Após muito buscar a origem do problema, não no Ubuntu, mas no python, descobri que alguns file descriptors estavam causando esse erro, por continuarem abertos quando ocorria o fork().  Corrigi da seguinte forma:

   def Daemonize(self):
      """
      Fork to became a daemon.
      """
      
      if not self.isDaemon:
         try:
            self.run()
         except KeyboardInterrupt:
            sys.exit(0)
         return
      
      os.chdir("/")
      pid = os.fork()
      
      if (pid > 0):
         os.close(sys.stdin.fileno())
         os.close(sys.stout.fileno())
         os.close(sys.stderr.fileno())
         sys.exit(os.EX_OK)
      else:
         pid = os.fork()
         
         if (pid > 0):
            os.close(sys.stdin.fileno())
            os.close(sys.stdout.fileno())
            os.close(sys.stderr.fileno())
            sys.exit(os.EX_OK)
         else:
            self.run()

então bastou fechar os descritores de arquivo do STDIN, STDOU e STDERR pra ter certeza que o daemon não sairia com o erro acima.

Happy hacking :-)

We use cookies

We use cookies on our website. Some of them are essential for the operation of the site, while others help us to improve this site and the user experience (tracking cookies). You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.