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]