Paramiko inside Python Daemon causes IOError

Viewed 1073

I'm trying to execute ssh commands using paramiko from inside a python daemon process. I'm using the following implementation for the daemon: https://pypi.python.org/pypi/python-daemon/

When the program is started pycrypto raises an IOError with a Bad file descriptor when paramiko tries to connect. If I remove the daemon code (just uncomment the last line and comment the two above) the ssh connection is established as expected.

The code for a short test program looks like this:

#!/usr/bin/env python2
from daemon import runner
import paramiko

class App():

    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_path =  '/tmp/testdaemon.pid'
        self.pidfile_timeout = 5

    def run(self):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.load_system_host_keys()
        ssh.connect("hostname", username="username")
        ssh.close()

app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()
#app.run()

The trace looks like this:

Traceback (most recent call last):
  File "./daemon-test.py", line 31, in <module>
    daemon_runner.do_action()
  File "/usr/lib/python2.7/site-packages/daemon/runner.py", line 189, in do_action
    func(self)
  File "/usr/lib/python2.7/site-packages/daemon/runner.py", line 134, in _start
    self.app.run()
  File "./daemon-test.py", line 22, in run
    ssh.connect("hostname", username="username")
  File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 311, in connect
    t.start_client()
  File "/usr/lib/python2.7/site-packages/paramiko/transport.py", line 460, in start_client
    Random.atfork()
  File "/usr/lib/python2.7/site-packages/Crypto/Random/__init__.py", line 37, in atfork
_UserFriendlyRNG.reinit()
  File "/usr/lib/python2.7/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 224, in reinit
_get_singleton().reinit()
  File "/usr/lib/python2.7/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 171, in reinit
    return _UserFriendlyRNG.reinit(self)
  File "/usr/lib/python2.7/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 99, in reinit
    self._ec.reinit()
  File "/usr/lib/python2.7/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 62, in reinit
    block = self._osrng.read(32*32)
  File "/usr/lib/python2.7/site-packages/Crypto/Random/OSRNG/rng_base.py", line 76, in read
data = self._read(N)
  File "/usr/lib/python2.7/site-packages/Crypto/Random/OSRNG/posix.py", line 65, in _read
    d = self.__file.read(N - len(data))
IOError: [Errno 9] Bad file descriptor

I'm guessing this has something to do with the stream redirection when the daemon spawns. I've tried to set them all to /dev/tty or even to a normal file but nothing works.

When I run the program with strace I can see that something tries to close a file twice and that's when I get the error. But I couldn't find out which file the descriptor actually points to (strace shows a memory location that doesn't seem to be set anywhere).

2 Answers
Related