Giter Club home page Giter Club logo

Comments (8)

drewyeaton avatar drewyeaton commented on September 23, 2024

I also had a similar issue with a Django site running under gunicorn. Moving the import into my view method solved the issue.

from paramiko.

bitprophet avatar bitprophet commented on September 23, 2024

tl;dr: I'd argue the problem here is the blanket closing of all file descriptors.

I can't think of a great way to guard against that within Paramiko itself (offhand) and the "best" way to try reopening the file descriptor when needed, would be in Crypto, which I personally have no control over.


A quick Google shows that people recognize the need to exclude files from the 'close all open file descriptors' step (e.g. one of the points in this SO answer).

In fact, the semi-official reference implementation for Python daemonization (which IMO is probably saner to use than an ActiveState code snippet, given it has a PEP and all :)) has an explicit option for this, files_preserve, as seen in the API section.

So I'd use that PEP implementation (it's on PyPI) and figure out how to get a reference to the file handle inside the RNG. (It doesn't seem obvious when I glance at Crypto.Random; I'd bet you could get a quicker answer by debugging your "Bad file descriptor" errors.)


Alternately, keep using your existing adhoc daemonization, but make the file descriptor closure section a blacklist instead of a whitelist: identify what other open FDs your code is generating, and explicitly close just those FDs.

I'll close the ticket as I don't think there's any good action to take on our end, but please keep me/us updated with what you find, and good luck!

from paramiko.

xraj avatar xraj commented on September 23, 2024

The problem is that there's no good way to get the FD from the RNG object. The attribute name is '__file' so it gets obfuscated. The the real problem is global state is being introduced from an import. What you should do is have each Transport object have its own RNG or have them share one through some kind of cache mechanism that doesn't create the RNG until it's needed.

from paramiko.

bitprophet avatar bitprophet commented on September 23, 2024

@xraj I was worried it might be something like that. I don't have time right now to chase this down, and I'm slightly wary that modifying how Paramiko uses the RNGs could introduce other bugs -- but if you or somebody else submits a patch exploring that change I would definitely reopen this issue & take a look at it.

from paramiko.

xraj avatar xraj commented on September 23, 2024

I'll look into making a patch; for now, I have a hacky work around.

import os
from resource import getrlimit, RLIMIT_NOFILE

def files_preserve_by_path(*paths):
    wanted=[]
    for path in paths:
        fd = os.open(path, os.O_RDONLY)
        try:
            wanted.append(os.fstat(fd)[1:3])
        finally:
            os.close(fd)

    def fd_wanted(fd):
        try:
            return os.fstat(fd)[1:3] in wanted
        except OSError:
            return False

    fd_max = getrlimit(RLIMIT_NOFILE)[1]
    return [ fd for fd in xrange(fd_max) if fd_wanted(fd) ]

daemon_context.files_preserve = files_preserve_by_path('/dev/urandom')

from paramiko.

ulope avatar ulope commented on September 23, 2024

@bitprophet Is there any chance you would reconsider this ticket?
I've just run into the same daemonizing problem as the OT and I'm not very enthused to use @xraj's (although rather clever) hack.

The basic problem is that paramiko unconditionally calls Crypto.Random.new() at module level import time in common.py.
This leads to /dev/urandom being opened as soon as paramiko is imported.

As far as I can tell this "global" RNG is used in relatively few places (I found 7 files that refer it).
Would you accept a PR that changes those places to use their own dedicated RNG instance instead?

from paramiko.

bitprophet avatar bitprophet commented on September 23, 2024

@ulope That sounds reasonable to me offhand, yea. I'm still working through my backlog, if that PR got opened already please link it here, and if not, please feel free to open one. Thanks!

from paramiko.

vaygr avatar vaygr commented on September 23, 2024

This is also the case when you work with GCP in libcloud from inside the daemon: https://github.com/apache/libcloud/blob/8bedf2472401186ca1038719a0cdd66155f833f5/libcloud/common/google.py#L96

from paramiko.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.