roger@zuken.co.jp (Roger Meunier) (08/09/90)
When a C++ program exits, it calls a list of destructors to clean up static data. But what happens when exit() is called after fork()? I ran into a problem with HP's implementation of Motif 1.0. For the XmText widget, they allow Chinese character input by setting up a connection with an input server. Apparently, they fork() the server on the first XmCreateText(). I noticed that in one of my applications, it was taking an extremely long time to create the first text widget (8+ sec.), and that core was being dumped during the creation. Looking at the core file with cdb, I noticed that exit() was being called from the routine that did the fork(), and that subsequently all my static destructors were being called, including one that caused the core to be dumped (it was calling XCloseDisplay()!). Why the *child* process should be trying to do this is beyond me. Has anyone else run into similar problems when fork()'ing in a C++ environment? Is this a design problem with the C++ static object clean-up strategy, or is HP's implementation of nlio forgetting to take C++ into account, or both? -- Roger Meunier @ Zuken, Inc. Yokohama, Japan (roger@zuken.co.jp)
mayer@hplabsz.HPL.HP.COM (Niels Mayer) (08/10/90)
In article <ROGER.90Aug9114200@rd11.zuken.co.jp> roger@zuken.co.jp (Roger Meunier) writes: >When a C++ program exits, it calls a list of destructors to clean up >static data. But what happens when exit() is called after fork()? > >I ran into a problem with HP's implementation of Motif 1.0. For the >XmText widget, they allow Chinese character input by setting up a >connection with an input server. Apparently, they fork() the server >on the first XmCreateText(). I noticed that in one of my applications, >it was taking an extremely long time to create the first text widget >(8+ sec.), and that core was being dumped during the creation. Looking >at the core file with cdb, I noticed that exit() was being called from >the routine that did the fork(), and that subsequently all my static >destructors were being called, including one that caused the core to >be dumped (it was calling XCloseDisplay()!). Why the *child* process >should be trying to do this is beyond me. > >Has anyone else run into similar problems when fork()'ing in a C++ >environment? Is this a design problem with the C++ static object clean-up >strategy, or is HP's implementation of nlio forgetting to take C++ into >account, or both? I don't think this has much to do with HP's implementation, nor C++ -- it is a general problem you have to watch out for when doing system(), popen() and fork() under X. Basically, your application's open connections to the X server take up file descriptors, and these are all faithfully copied upon vfork()/fork().... To fix the problem, you need to close the file descriptors after you fork, e.g.: pid_t pid; if((pid = vfork()) == 0) { for(i=3;i<_NFILE;i++) /* close all fd except stdin, stdout, and stderr */ close(i); ... } As to why the X implementation doesn't set the close-on-exec flag via fcntl() to prevent this problem, only the experts know. -------------------- I'm trying to deal with a similar problem right now as a matter of fact. Does anybody have a public domain (or non-restrictive-copyright) version of popen() and system() that you'd be interested in sharing??? Actually, system() is easy... But I'm too lazy to go figure out how to do popen() without sullying the pristine "clean-room" environment of my mind. ------------------------------------------------------------------------------- Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com Human-Computer Interaction Department Hewlett-Packard Laboratories Palo Alto, CA. *
roger@zuken.co.jp (Roger Meunier) (08/20/90)
In article <5768@hplabsz.HPL.HP.COM> mayer@hplabsz.HPL.HP.COM (Niels Mayer) writes: >I don't think this has much to do with HP's implementation, nor C++ -- it >is a general problem you have to watch out for when doing system(), popen() >and fork() under X. > >Basically, your application's open connections to the X server take up file >descriptors, and these are all faithfully copied upon vfork()/fork().... > >To fix the problem, you need to close the file descriptors after you >fork, ^^^ I am not the one who is fork()'ing; Motif is. My destructors get called when the kanji input server (/usr/lib/nlio/serv/X11/xj0input) is spawned, because exit() (rather than _exit()?) is being called in the child environment. My destructor calls XCloseDisplay(), at which time some error occurs, and core is dumped because the error message cannot be output. Here's a sample stack trace of the core dump: 0 __doprnt + 0x6 1 __fprintf + 0x32 2 __XIOError + 0x30 3 __XReply + 0x20 4 _XSync + 0x52 5 _XCloseDisplay + 0x64 ... 10 _STDmain_cxx_ () 11 _exit + 0x38 12 __XIOError + 0x80 13 __XReply + 0x20 14 _XSync + 0x52 15 _XCloseDisplay + 0x64 ... 49003 _STDmain_cxx_ + 0x10 49004 _exit + 0x38 49005 _XHPInputChinese_t + 0x652 49006 _XHPNlioctl + 0xac 49007 _XmTextInputCreate + 0x218 49008 _XmTextSetHighlight + 0x2f6 49009 __XtAddDefaultConverters + 0x520 49010 __XtCreate + 0x1da 49011 _XtCreateWidget + 0xac 49012 _XmCreateText + 0x1c ... In this case, the error during XCloseDisplay() causes a call to exit(), which calls the destructors *again*, ad infinitum. This doesn't occur every time; usually _XIOError() bombs at the first _doprnt() and never gets to call exit(). This raises another question: if static destructors can trigger an error condition which in turn triggers a call to exit(), is there some standard method for avoiding the above infinite looping? -- Roger Meunier @ Zuken, Inc. Yokohama, Japan (roger@zuken.co.jp)
nick@esacs.UUCP (Nikolaos Tsivranidis) (03/08/91)
Suppose you *have* to fork() a process and *not* do an exec(). You end up with a child process that shares all the data of the parent (including her open file descriptors). Presumably you can now create a new window, and operate on the data space of the parent process while displaying on the windows of the child process. Questions: (1) This doesn't sound right to me, but I don't know exactly where the problems are. Is there a problem? (2) If one closes the Xserver connection and calls XtInitialize again, what happens? (If a segmentation fault produced a sound proportional to the seriousness of the error, how big would this sound be?) (3) If you have a lot of *application* specific data to display, and you would like to put the application in the background while displaying the data, what do you do? Remember, you only create the windows and display the data according to an application specific way. (If you don't understand (3) it is probably because I don't understand it either, this is somebody else's question.) - nick -