3

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!

2
  • 3
    the simplest fix is to avoid opening files, sockets before the daemonization. Commented Mar 1, 2013 at 5:56
  • Thanks, that's sorted it :-) Commented Mar 1, 2013 at 6:08

1 Answer 1

8

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.