You would get the same problem if you wrote a C GTK+ program that forked
and you called exit().  In this case, you would call _exit() which
bypasses all atexit handlers.

In python this translates to using os._exit() instead of sys.exit().

James Henstridge.

--
Email: [EMAIL PROTECTED]
WWW:   http://www.daa.com.au/~james/


On 22 Feb 1999, Hrvoje Niksic wrote:

> OK, here is another interesting problem which took several hours to
> track.  When a Gtk program forks off, it inherits the X file
> descriptors from its parent.  It seems that when I call sys.exit(),
> Gdk gains control (either through atexit() or through a PyGtk cleanup
> intercepting SystemExit), interacts with the X file descriptors,
> totally hosing the parent.  As a result, the parent's Gdk reports IO
> errors and aborts.
> 
> The typical code where this problem bites looks like this:
> 
> pid = os.fork ()
> 
> if pid == 0:
>   # Child
>   try:
>     os.execlp ("foo", "bar", "baz")
>   except:
>     # An error occurred during execlp; exit immediately
>     sys.exit (127)
> 
> In a Gtk program, if the execlp raises an exception the *parent* will
> coredump.  If you replace `sys.exit(127)' with
> `os.kill(getpid(),signal.SIGTERM)', no coredump happens because the
> Gdk stuff never gets invoked.
> 
> Fixes/workarounds include, in the increasing order of usefulness:
> 
> 1) The child closing all the file descriptors except the ones you're
>    interested in.  This is a gross hack that looks like this:
> 
>     for fd in range(32):
>       if not fd in (0, 1, 2, self.writefd):
>         try:
>           os.close (fd)
>         except:
>           pass      # Ignore EBADF
> 
> 2) The child closing only the X file descriptor.  This would require
>    Gdk to somehow export the descriptors it uses, so that Python child 
>    knows what to close.  This is also a gross hack, but faster than
>    the above.
> 
> 3) Making sure that random Gdk code isn't called at exit time.
> 
> 4) Providing a function that cleanly shuts down Gtk/Gdk, *without*
>    messing with the descriptors (except for perhaps closing them), and 
>    *without* calling any callbacks.  This, cleanest solution, would
>    also assume that #3 is being done, for programs that don't bother
>    to call the function.
> 
> The test program is appended below.  It forks off and exits the child
> after a second's sleep.  For me, the parent then coredumps with this
> message:
> 
>     Gdk-ERROR **: an x io error occurred
>     aborting...
> 
> If you uncomment the os.kill(...) statement, it works as expected.
> 
> #!/usr/local/bin/python
> 
> from gtk import *
> import os, sys, signal, time
> 
> def fork_off ():
>     pid = os.fork ()
> 
>     if pid == 0:
>         # Child
>         time.sleep (1)
>         #os.kill (os.getpid (), signal.SIGTERM)
>         sys.exit (127)
>     else:
>         # Parent
>         os.wait ()
>     return FALSE
> 
> w = GtkWindow ()
> w.connect ("destroy", mainquit)
> w.show_all ()
> # Call fork_off() as soon as mainloop() starts.
> timeout_add (1, lambda *args: fork_off ())
> mainloop ()
> To unsubscribe: echo "unsubscribe" | mail [EMAIL PROTECTED]
> 

To unsubscribe: echo "unsubscribe" | mail [EMAIL PROTECTED]

Reply via email to