zjmw0a@apctrc.trc.amoco.com (Joe M. Wade) (09/08/89)
In an effort to separate functionality between programs, one of my colleagues (cohorts?) produced code using popen to start another process which would use X to plot data created by the initial process. He then found the initial process had to be forked so that the command widget which spawned the popen would return to its sensitive state. Everything works hunky-dory except for one thing-the initial process dies when the quit button is pushed, but the window doesn't go away until the spawned-off process is also exited. Killing the window manager didn't help, although it seems as though that would probably be the source of the difficulty. Below is a short piece of code demonstrating the problem. It produces two buttons, fork and quit. If you hit fork, it does a popen of this same process. Try using the quit button of the original process and its pid disappears, but the windows remain. Pertinent info: Sun 3/60 OS 4.0.1, X11R3, twm #include <stdio.h> #include <math.h> #include <X11/Xlib.h> #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Xatom.h> #include <X11/Cardinals.h> #include <X11/Box.h> #include <X11/Command.h> #include <X11/Shell.h> void quit(); void fork_process(); main(argc, argv) int argc; char *argv[]; { extern void time_out(); Widget toplevel, outerform, quitter, forker; int screen; Display *display; Arg arg[5]; int fork_value; /* * fork this process */ if ( (fork_value = fork()) != 0 ) exit(0); toplevel = XtInitialize(NULL, "XLabel", NULL, 0, &argc, argv); display = XtDisplay(toplevel); screen = XDefaultScreen(display); outerform = XtCreateManagedWidget("outerform", boxWidgetClass, toplevel, (Arg*) arg, NULL); XtSetArg(arg[0], XtNlabel, (String) "Quit"); quitter = XtCreateManagedWidget("Quit", commandWidgetClass, outerform, (Arg*) arg, ONE); /* * Create a command widget to popen a new process */ XtSetArg(arg[0], XtNlabel, (String) "Fork"); forker = XtCreateManagedWidget("Fork", commandWidgetClass, outerform, (Arg*) arg, ONE); XtAddCallback(quitter, XtNcallback, quit, &toplevel); XtAddCallback(forker, XtNcallback, fork_process, NULL); XtRealizeWidget(toplevel); time_out(); XtMainLoop(); } void fork_process() { FILE *fptr; /* * start a new process */ fptr = popen( "fork", "r"); pclose( fptr ); return; } void quit ( button, top_widget ) Widget button; caddr_t *top_widget; /* * destroy the top level widget and exit */ { XtDestroyWidget( *((Widget *) top_widget) ); exit (0); } Any info/input would be greatly appreciated. * * * * * * * * * * * * * * * * * * * * * * * Joe M. Wade (zjmw0a@apctrc.trc.amoco.com) (918) 660-4387 * * Amoco Research Center * 4502 E. 41st St. * Tulsa, OK 74102 * * * * * * * * * * * * * * * * * * * * * * *
DCOOPER%ESDSDF.DECnet@CRDGW1.GE.COM (09/08/89)
Excerpt of message <1015@apctrc.UUCP> from Joe M. Wade: > > ...Everything works hunky-dory except for one > thing-the initial process dies when the quit button is pushed, > but the window doesn't go away until the spawned-off process is > also exited. > This bug has bitten me and a number of others. The problem is that the socket is not closed on exec, therefore the window does not disappear until the socket is finally closed when the process terminates. My solution was to set close-on-exec by: #include <fcntl.h> ... fcntl(ConnectionNumber(XtDisplay(toplevel)), F_SETFD, 1); where toplevel is the widget returned from XtInitialize. I submitted this problem to xbugs but it was rejected. (denial is the first step in my debugging process too :-) Dwight Cooper GE Electronic Systems Dept. dcooper%esdsdf.decnet@crd.ge.com
spencer@eecs.umich.edu (Spencer W. Thomas) (09/08/89)
Problem summary: process forks, then exits, but windows stay up until subprocess also exits. Solution: (I think) close the display connection after fork and before exec. You can set the "close on exec" flag for the display connection by: #include <fcntl.h> fcntl( ConnectionNumber(display), F_SETFD, 1 ); Oddities dept: I had to make one other change to get the program to work as advertised: I had to change the pclose to a close, apparently pclose (Sun OS 4.0.1) waits for the child to exit? -- =Spencer (spencer@eecs.umich.edu)
mouse@lightning.mcrcim.mcgill.EDU (der Mouse) (03/06/91)
> I'm writing a Motif application which requires me to fork() and > continue processing with the same windows & environment. The first > time I try to bring up a new window after the fork(), I get the > following error: > X Error of failed request: BadIDChoice (invalid resource ID chosen for this connection) [...] > I think that I have to create a new connection to the original > display... but I don't know how to do that. (This is the deepest > I've had to delve into Xlib.) You are correct. When a process with an X connection open fork()s, at most one of the resulting two processes can do anything to the connection (where XCloseDisplay counts as doing something). One of the processes should probably close the connection out from under Xlib, with close(XConnectionNumber(dpy)), and *then* XCloseDisplay() (to free up the Xlib data structures) and open a new connection. How this relates to toolkits and higher layers I have no idea. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu