thesharp / daemonize

daemonize is a library for writing system daemons in Python.
MIT License
445 stars 64 forks source link

DNS lookup before fork causes lookup failure after fork on OSX #75

Open nickodell opened 4 years ago

nickodell commented 4 years ago

I'm running into a really specific and weird bug on OSX.

Reproduction instructions

Use OSX. I am using 10.15.4 right now; I don't know if the specific version matters.

Install daemonize 2.5.0.

Run this script:

#!/usr/bin/env python3
import socket
from daemonize import Daemonize

def run():
    print(socket.gethostbyname('google.com'))

if __name__ == '__main__':
    print(socket.gethostbyname('google.com'))
    daemon = Daemonize(app="monitor_script", pid="./test.pid", action=run, foreground=False)
    daemon.start()

Symptoms of bug

Before forking, the Python program can successfully do a DNS lookup.

The following message appears in Console.app under Log Reports > system.log:

Jul 31 14:22:24 Nicks-MacBook-Pro monitor_script: Starting daemon.
Jul 31 14:22:24 Nicks-MacBook-Pro monitor_script: Traceback (most recent call last):
Jul 31 14:22:24 Nicks-MacBook-Pro monitor_script:   File "/Users/nick/.pyenv/versions/3.6.10/lib/python3.6/site-packages/daemonize.py", line 248, in start
Jul 31 14:22:24 Nicks-MacBook-Pro monitor_script:     self.action(*privileged_action_result)
Jul 31 14:22:24 Nicks-MacBook-Pro monitor_script:   File "test.py", line 7, in run
Jul 31 14:22:24 Nicks-MacBook-Pro monitor_script:     print(socket.gethostbyname('google.com'))
Jul 31 14:22:24 Nicks-MacBook-Pro monitor_script: socket.gaierror: [Errno 8] nodename nor servname provided, or not known
Jul 31 14:22:24 Nicks-MacBook-Pro monitor_script: Stopping daemon.

Variations tried

I have run the reproduction script on Linux, and it can successfully resolve DNS before and after forking. (This is why I marked this as an OSX-specific bug.)

I have run the reproduction script without the first DNS lookup. This works.

I have run the reproduction script with foreground=True. This works.

I've tried putting a sleep between the two DNS lookups. This doesn't help.

Workaround

Don't do DNS lookups before forking.

miigotu commented 3 years ago

I don't consider this a bug. If foreground, the file descriptors wouldn't be closed, otherwise they are and socket (SocketIO) uses file descriptors which are kept in a reference list in stdlib socket. If you close them by daemonization, stdlib does not know that descriptors it opened are closed. You could get the fd from socket and pass it to the daemonize call to keep it alive.