Daemon beendet sich ohne Angabe von Gründen bei Dateizugriff

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
bf
User
Beiträge: 7
Registriert: Mittwoch 18. Februar 2009, 10:14

Ich fange gerade an mit Python zu programmieren und suche mir das schickste aus dem Netz zusammen, daher nehmt es mir nicht übel, wenn ich etwas übersehen habe, was einem routinierten "Pythoner" sofort auffällt ;)

Ich schreibe gerade einen daemon der per uart (pyserial) mit einer Gegenstelle reden soll und den mpd steuern (mpd).
Dabei verwende ich daemon für den Daemon. Vorher hatte ich das Ganze schon in C geschrieben, aber das ist mir auf dauer zu viel Aufwand, python nimmt einem da ja schon einiges ab...

Wenn ich jetzt im Code z.B. in eine Datei schreiben will, dann beendet sich der daemon ohne irgend eine Meldung. Genauso wen ich ins syslog schreiben will.

Code: Alles auswählen

import syslog
import daemon
...
datei = open('datei', 'a')
daemon.daemonize()
datei.write('bla')
...
syslog.syslog(0, 'bla')
...
Dabei ist es völlig egal ob ich die Datei nach oder vor dem daemon.daemonize öffne. Erst sobald er schreiben soll, verabschiedet er sich. Das öffnen macht ihm noch nichts aus.

Ich hoffe ihr könnt mir sagen, woran das liegt.


Achso, noch eine kleine Frage, welche aber nicht wirklich wichtig ist.
Wenn ich in einer bash einen Prozess mit & in den Hintergrund schiebe (also quasi zum Daemon machen), dann erscheinen dessen Konsolenmeldungen immer noch auf der Konsole. Weiss einer wie ich hier ein print wieder auf die Konsole umleiten kann?
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Benutz doch mal pdb, den Python Debugger, und schau dir das ganze Stück für Stück an.
dann erscheinen dessen Konsolenmeldungen immer noch auf der Konsole. Weiss einer wie ich hier ein print wieder auf die Konsole umleiten kann?
:?:
bf
User
Beiträge: 7
Registriert: Mittwoch 18. Februar 2009, 10:14

Also einen pdb konnte ich nicht finden, nur einen winpdb und damit komme ich herzlich besch****n zurecht. Was ich bisher herausgefunden habe ist folgendes.
Ich habe den Code ungefähr so:

Code: Alles auswählen

import daemon
import os
import sys
import time
import serial
import ConfigParser
import mpd
import getopt
import pwd
import syslog
import string
...
...
...
def mpd_Play():
        bla()

def mpd_Next():
        bla()
...
...
daemon.daemonize()
syslog.syslog(0, 'bla')
...
def my_daemon:
        bla()
        blubb()
        das_eigentliche_hauptprogramm()
...
...
my_daemon()
Die Imports sind genau so, wie ich sie im Code habe.
Da hängt er sich auf, aber schreibe ich wie im Eingangsbeitrag das stark verkürzte hin, dann geht es seltsamerweise...

Code: Alles auswählen

#!/usr/bin/env python

import syslog
import daemon

datei = open('datei', 'a')
daemon.daemonize()
datei.write('bla')
datei.close()
syslog.syslog(0, 'bla')
while(1):
        a=0
bla steht in datei und im syslog und ps aux | grep python zeigt mir den Prozess auch an...
Auch wenn ich alle imports reinpacke, geht es.

Wegen dem Debugger, kann mir jemand sagen, nach WAS ich Ausschau halten soll?
Etwas, was mir aufgefallen ist, ist, sobald er (siehe code ganz oben) my_daemon() aufruft, kommt im Frame mit dem Script das Script zu deamon und es wird zwar noch in der Konsole angezeigt was vor meinem daemon.daemonize() angezeigt wird (print) aber ich sehe im debugger kein einziges mal wie ich dort einen Schritt weiter gehe, er geht direkt in das Script zu daemon und landet dort:

Code: Alles auswählen

def __fork():
    global g_forktid
    
    if not g_fignorefork:
        g_forktid = setbreak()

    #
    # os.fork() has been called. 
    #
    # You can choose if you would like the debugger
    # to continue with the parent or child fork with
    # the 'fork' console command.
    # 
    # For example: 'fork child' or 'fork parent'
    # Type: 'help fork' for more information.
    #
    # WARNING: 
    # On some Posix OS such as FreeBSD, 
    # Stepping into the child fork can result in 
    # termination of the child process.
    #
    # *** RPDB2 SAYS: Read the entire comment! ***
    #
    return g_os_fork()
Einen weiteren step später:

Code: Alles auswählen

def _fork():
    try:
        return os.fork()
    except OSError, e:
        raise DaemonException, 'Cannot fork: %s [%d]' % (e.strerror, e.errno)
Weiter, und hier steigt er dann aus, dort wo das "######## HIER!" steht, was aber, wie ich sehe doch nur für den Vaterprozess sein soll...

Code: Alles auswählen

def daemonize(noClose=False):
    """
    Convert the calling process into a daemon.

    @type noClose:  boolean
    @param noClose: If True, don't close the file descriptors. Useful
                    if the calling process has already redirected file
                    descriptors to an output file. WARNING: Only set this
                    parameter to True if you're SURE there are no open file
                    descriptors to the calling terminal. Otherwise, you'll
                    risk having the daemon re-acquire a control terminal,
                    which can cause it to be killed if someone logs off that
                    terminal.

    @raise DaemonException: Error during daemonizing
    """
    global log

    if os.name != 'posix':
        log.warn('Daemon is only supported on Posix-compliant systems.')
        return

    try:
        # Fork once to go into the background.

        log.debug('Forking first child.')
        pid = _fork()
        if pid != 0:
            # Parent. Exit using os._exit(), which doesn't fire any atexit
            # functions.
            os._exit(0)
    
        # First child. Create a new session. os.setsid() creates the session
        # and makes this (child) process the process group leader. The process
        # is guaranteed not to have a control terminal.
        log.debug('Creating new session')
        os.setsid()
    
        # Fork a second child to ensure that the daemon never reacquires
        # a control terminal.
        log.debug('Forking second child.')
        pid = _fork()
########## HIER !
        if pid != 0:
            # Original child. Exit.
            os._exit(0)
..
..
Unix confuses me :P
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Was mich mal interessieren würde ... bei dem 'try' im letzten Code-Beispiel: Wie sieht da dein 'except' aus?
bf
User
Beiträge: 7
Registriert: Mittwoch 18. Februar 2009, 10:14

Also bei dem try und sonst im Code ändert sich nix.
Hier ein Screenshot von den Exceptions (tut mir leid, aber abtippen tu ich die nich, solang ich nicht weiss was denn nun genau ;) ).
Dies kommt, gleich am Anfang, wenn ich auf "Launch" gehe.
Das kommt dann nach dem ersten Step, also import daemon
Und vom ersten Step an (das Dritte Bild) bis zum Schluss (erstes Bild) sieht das doch auch relativ gleich aus...

PS: Umpf,da fängt man eine vermeintlich "einfachere Sprache" an und fühlt sich wie bei den ersten gdb/C Schritten :D
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Der letzte Link funktioniert leider nicht.

Ich meinte eigentlich, wie die 'except' -Codezeile aussieht. Ich vermute, daß dort einfach nur 'except:' steht, und er deshalb keine Fehlermeldung ausgibt.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Was Pekh anspricht, wirds wohl sein. An der Stelle, an der es nicht weitergeht, wird wohl eine Exception durch ein einfaches "except:" geschluckt. Zeig doch mal das komplette try: Konstrukt. Sieht also nach einem Bug im daemon Modul aus.

pdb ist ein Modul aus der Standardlibrary, winpdb ist wie ich meine einfach nur eine grafische Oberfläche dafür. Meistens reicht es, an eine interessante Stelle im Code

Code: Alles auswählen

import pdb; pdb.set_trace()
einzufügen, pdb aktiviert sich dann automatisch, sobal man dorthin kommt. Kann man dann auch mit einem "sed -e "/import pdb;/d" -i datei" bequem löschen lassen ;)

Und irgendwo scheint wohl ein "nt" Modul zu fehlen? Das mit dem Mapping Key schaut auch reichlich komisch aus. Wird wohl am besten sein, du wendest dich an den Maintainer des daemon Moduls.
PS: Umpf,da fängt man eine vermeintlich "einfachere Sprache" an und fühlt sich wie bei den ersten gdb/C Schritten
gdb macht aber weniger Spaß als pdb :P
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

lass das Programm einfach mal ohne deamon laufen ich glaube nämlich nicht dass es an deamon liegt(der forkt einfach nur)
bf
User
Beiträge: 7
Registriert: Mittwoch 18. Februar 2009, 10:14

Maan, ich sage doch, dass "mein daemon spinnt" und ich den repariert haben will und dass es ohne funzt -.-
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

bf hat geschrieben:Maan, ich sage doch [...] dass es ohne funzt -.-
Nein hast du nicht. Zum 3. Mal: Was steht bei except?
Antworten