Daemonizing a python script with python-daemon - socket trouble
Question: I'm try to daemonize some code, but I'm having some trouble.

If I call the code with tklogger(), it runs just fine. However, if I call it
in the daemon context, I get the following trace:

    
    
    Traceback (most recent call last):
      File "./tklogger.py", line 103, in <module>
        tklogger()
      File "./tklogger.py", line 41, in tklogger
        conn, addr = s.accept()
      File "/usr/lib/python2.6/socket.py", line 195, in accept
        sock, addr = self._sock.accept()
    socket.error: [Errno 9] Bad file descriptor
    close failed in file object destructor:
    IOError: [Errno 9] Bad file descriptor
    

My code is as follows:

    
    
    #!/usr/bin/python
    
    # tklogger, a TK10X GPS tracking device logger
    
    import socket
    import time
    import daemon
    
    HOST = ''                       # Bind to all interfaces
    PORT = 9000                     # Arbitrary non-privileged port
    IMEI = '359710040656622'        # Device IMEI
    REQUEST_DATA = 1                # Do we want to request data?
    INTERVAL = 30                   # How often do we want updates?
    LOGDIR = '/var/log/tklogger/'   # Where shall we log?
    
    # END CONFIG
    
    # Establish socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # allow re-use of the address
    s.bind((HOST, PORT))
    s.listen(1)
    
    # Open log files
    logger = open(LOGDIR + 'tklogger.log', 'a')
    deviceLog = open(LOGDIR + IMEI + '.csv', 'a')
    
    def sendTracker(DATA):
        conn.send(DATA)
        log("\t<< " + DATA)
    
    def log(DATA):
        #print (DATA)
        logger.write(DATA + '\n')
        logger.flush()
    
    def tklogger():
        # Accept connections as they come
        while 1:
            global conn
            conn, addr = s.accept()
            strNow = time.strftime("(%d/%m/%Y %H:%M:%S)", time.localtime(time.time()))
            log(strNow + ' Accepted connection from ' + addr[0])
    
            # Fetch data from the socket
            while 1:
                data = conn.recv(1024)
                if not data: break
                data = data.rstrip()
                log("\t>> " + data)
    
                # Check for logon & send data request
                if data == '##,imei:' + IMEI + ',A;':
                    sendTracker('LOAD')
                    if REQUEST_DATA:
                        time.sleep(5)
                        request = '**,imei:' + IMEI + ',C,' + str(INTERVAL) + 's'
                        sendTracker(request)
    
                # Check for heartbeat
                if data == IMEI + ';':
                    sendTracker('ON')
    
                # Parse actual data
                if data[:20] == 'imei:' + IMEI:
    
                    # Split into fields
                    # id, mode, dateTime, ??, LBS??, ??, fixType??, lat, N/S, lon, E/W, speed?, bearing?
                    fields = data.split(',');
                    if fields[6] == 'A':
    
                        # Hopefully we have the protocol right...
                        try:
                            # Convert to degress decimal.
                            latDeg = round(float(fields[7][:2]) + (float(fields[7][2:]) / 60.0), 5)
                            lonDeg = round(float(fields[9][:3]) + (float(fields[9][3:]) / 60.0), 5)
                            if fields[8] == 'S': latDeg = -latDeg
                            if fields[10] == 'W': lonDeg = -lonDeg
    
                            # Date & time
                            msgDate = fields[2][4:6] + '/' + fields[2][2:4] + '/' + fields[2][:2]
                            msgTime = fields[2][6:8] + ':' + fields[2][8:]
    
                            # Speed
                            speed = round(1.852 * float(fields[11]), 2)
    
                            # Bearing 
                            bearing = float(fields[12].rstrip(';'))
    
                            # Log the device data
                            deviceLog.write(msgDate + ',' + msgTime + ',' + str(latDeg) + ',' + str(lonDeg) + ',' + str(speed) + ',' + str(bearing) + '\n')
                            deviceLog.flush()
    
                        # Just in case something goes wrong though
                        except: pass
    
            conn.close()
            strNow = time.strftime("(%d/%m/%Y %H:%M:%S)", time.localtime(time.time()))
            log(strNow + ' Connection from ' + addr[0] + ' closed')
    
    
    with daemon.DaemonContext(stderr = logger):
        tklogger()
    

Suggestions would be appreciated!


Answer: The act of daemonizing kills all existing sockets. Therefore, you must open
your socket `s` after daemonization (inside the DaemonContext).

