spanki@color.ced.berkeley.edu (Frank Goodman) (02/24/90)
I've got a few questions about the quit functions of core clients in the R4 distribution. I'm writing an application that uses one of my own widgets under X11 R4 Athena. For a while, I was following the examples of the source code in $TOP/clients. Most of these clients exit via a function that looks similar to this. Exit(w, call, client) Widget w; caddr_t call, client; { XtDestroyApplicationContext(app_con); exit(0); } Now, from my own trauma with my application I have found that this will NOT call ANY of the widget's destroyCallback procedures. I now understand why (thanks to Paul Asente: asente@decwrl.dec.com). Now, many of the athena widgets do indeed have destroy callbacks, so it would seem that any application that exits in the above fashion is "doing the wrong thing". Would you (Consortium Staff), say this is true? The reason I bring this up, is basically for clarification for myself, and others. The documentation covers XtDestroyWidget, and XtDestroyApplicationContext, but it doesn't address this phenomenom at all. If a widget writer puts a destroycallback into their widget, there is assumed to be a good reason for this. Now, In my eyes an application writer should not have to look through the widget code to see if the destroy callback is "worth calling" or not. In my case, it was imperative that my destroyCallback got called, beacuse it has to remove a 30MB tmp file. The hack I'm using (again, thanks to Paul Asente) is as follows: void Exit() { xtUnmapWidget(top); XtDestroyWidget(top); /* global flag */ exitFlag = True; } MainLoop() { while (1) { /* dpy, and app_con are global */ XEvent event; XtAppNextEvent(app_con, &event); XtDispatchEvent(&event); if (exitFlag) { XFlush(dpy); break; } } XtDestroyApplicationContext(app_con); exit(0); } In this way, by the time the flag is set, all the events (XtCallCallbacks) are already on the que, so XFlush, moves 'm on through, then we exit. I'm wondering what the deal is? Why did the Consortium Staff neglect this aspect of exiting? It is well documented, that XtDestoryWidget is a two pass operation, it's equally well ignored by the applciations in the distribution. What gives? Furthermore, I'm even more curious if this is the cause of the notorious "Memory Leaks". In other words, I'm curious if every application that uses widgets, and exits without waiting for these callbacks are leaving stuff in the server and therefore it would seem to continually grow? Also, Since every application that uses widgets has a toplevelshell, could there perhaps be some sort of event dispatched when that shell is finally detroyed? Maybe you could then pass the toplevelwidget to a new XtAppMainLoop, and it would exit appropriately when the shell is dead? I would be really interested to hear what people think about this. My hope is that someone can give me an explanation for these inconsistencies or, explain to me (nicely please) why I don't know what I'm talking about. Thanks Frank. --------------------------------------------------------------------------- Frank Goodman arpa: spanki@CED.Berkeley.EDU University of California, Berkeley or: spanki%CED@jade.Berkeley.EDU College of Environmental Design uucp: ...hplabs!ucbvax!ced!spanki S.I.S Research Laboratory phone: Novelty item, not necessary ---------------------------------------------------------------------------
rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (02/25/90)
Furthermore, I'm even more curious if this is the cause of the notorious "Memory Leaks". In other words, I'm curious if every application that uses widgets, and exits without waiting for these callbacks are leaving stuff in the server and therefore it would seem to continually grow? "The server don' 'llow no resource leakin' 'roun here." The server doesn't care "how" the client terminates, it always frees all resources created (unless the client has explicitly asked for a Retain CloseDownMode).
kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) (02/27/90)
> Exit(w, call, client) > Widget w; > caddr_t call, client; > { > XtDestroyApplicationContext(app_con); > exit(0); > } > Now, from my own trauma with my application I have found that this will NOT > call ANY of the widget's destroyCallback procedures. I now understand why > (thanks to Paul Asente: asente@decwrl.dec.com). Now, many of the athena > widgets do indeed have destroy callbacks, so it would seem that any > application that exits in the above fashion is "doing the wrong thing". > Would you (Consortium Staff), say this is true? Since both the operating system and the X server are clever enough to free up all resources associated with the client, it should be enough to just call exit(). You can certainly be more clever, but it didn't seem worth putting a bunch of code that doesn't accomplish anything into all the example programs. Chris D. Peterson MIT X Consortium Net: kit@expo.lcs.mit.edu Phone: (617) 253 - 9608 Address: MIT - Room NE43-213
spanki@color.ced.berkeley.edu (Frank Goodman) (02/27/90)
In article <9002261658.AA28416@expo.lcs.mit.edu>, kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) writes: > > Since both the operating system and the X server are clever enough to free > up all resources associated with the client, it should be enough to just call > exit(). You can certainly be more clever, but it didn't seem worth putting a > bunch of code that doesn't accomplish anything into all the example programs. > > > Chris D. Peterson > MIT X Consortium I think the important issue here is that application programmers don't know the contents or mechanisms of a widget. A widget writer is supossed to destroy everything that needs to be destroyed in the destroy callback. An application writer doesn't know what gets destroyed there, and shouldn't have to go look. He should ALWAYS allow the widgets to exit properly. Wether or not the OS or Server free the X resources, neither one are going to remove my widget's 36 meg temp file. Something an application writer shouldn't have to worry about when he uses my widget. However, if he follows the core examples he will fill his filesystem pretty darn fast and accuse me of writing a bad widget. I look to the core programs as examples, and I'm sure others do too. It seems to me that they should either "do the right thing" or explain why they don't. Just because you all know that none of the Athena widgets really need a destroy callback (given the server and OS), doesn't mean that it is safe to assume this for all widgets. Why did your widget writers even bother putting in these callbacks, if you summarily ignore them? If they are truely meant as "examples", than I will argue that it was worth the extra code to exit correctly. Your examples make it harder for those of us out here writing more sophisticated/powerful widgets because applications writers who follow those examples will undoubtedly have as much trouble as I did figuring out the cause of their problem. If widget abstractions are supposed to be "private" from the application, then widget writers should be able to work under the assumption that application writers will "know how" to use the widgets. However, neither the examples, nor the documentation really address this phenomenon and my feelings are that maybe they should. -Frank. P.S. I don't mean to belabor the point, but I feel this is an important issue. By exiting the way you suggest, you are implying that application writers should also do this. I disagree. --------------------------------------------------------------------------- Frank Goodman arpa: spanki@CED.Berkeley.EDU University of California, Berkeley or: spanki%CED@jade.Berkeley.EDU College of Environmental Design uucp: ...hplabs!ucbvax!ced!spanki S.I.S Research Laboratory phone: Novelty item, not necessary ---------------------------------------------------------------------------
ben@hpcvlx.cv.hp.com (Benjamin Ellsworth) (02/28/90)
OK, I give. The twists and turns of this thread have confused me. Is the question "How to destroy a widget hierarchy?" If you want to destroy a widget and all of its children you call XtDestroyWidget. Due to some funky-ness in the Xt implementation you sometimes have to handshake an event through, but XtDestroyWidget will destroy the widget and (if the widget was written correctly) all of the private data associated with the widget. What's so hard about that? Is the question "How do you exit an Xt application?" My personal favorite is "exit(0);" This is UN*X and exit has well defined behavior on all systems that I'm familiar with. I suppose that if one was particularly paranoid one could destroy all widget hierarchies, then destroy all app contexts, and then exit. What's hard about that? Of course, I could have missed the point entirely... ----------------------------------------------------------------------- Benjamin Ellsworth | ben@cv.hp.com | INTERNET Hewlett-Packard Company | {backbone}!hplabs!hp-pcd!ben | UUCP 1000 N.E. Circle | (USA) (503) 750-4980 | FAX Corvallis, OR 97330 | (USA) (503) 757-2000 | VOICE ----------------------------------------------------------------------- All relevant disclaimers apply. -----------------------------------------------------------------------
kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) (03/01/90)
> > me > Frank me > > Since both the operating system and the X server are clever enough to free > > up all resources associated with the client, it should be enough to just call > > exit(). You can certainly be more clever, but it didn't seem worth putting a > > bunch of code that doesn't accomplish anything into all the example programs. > I think the important issue here is that application programmers don't know the > contents or mechanisms of a widget. A widget writer is supossed to destroy > everything that needs to be destroyed in the destroy callback. After thinking about this some more I agree something else should be happening here. We will look into solving the problem. Chris D. Peterson MIT X Consortium Net: kit@expo.lcs.mit.edu Phone: (617) 253 - 9608 Address: MIT - Room NE43-213
asente@decwrl.dec.com (Paul Asente) (03/01/90)
In article <1990Feb26.192750.15430@agate.berkeley.edu> spanki@color.ced.berkeley.edu (Frank Goodman) writes:
...a bunch of stuff berating the MIT applications for ust exiting instead
of destroying their widgets...
When you write a non-toolkit program that uses malloc, do you explicitly
free all of the allocated storage before you exit? Of course you don't.
You know that malloc doesn't consume any system resources that won't be
recovered when you program exits. This places some future constraints on
malloc (that it *never* be changed to consume resources that need explicit
freeing) but it's considered a reasonable tradeoff not to have to do a
whole slew of completely useless work before you exit the program.
The situation with widgets is completely analogous. If a widget consumes
a resource that needs explicit freeing, the widget documentation had
better document this so that the application can be sure to destroy the
widget before exiting. Otherwise there is no point in having the
program spend time freeing storage, destroying windows, freeing fonts and
graphics contexts, and so forth when these things would all be done
automatically (and much more quickly) if the application just exits.
The destroy methods and callbacks are mostly for applications that need to
continue after destroying some or all of their widgets. The toolkit was
not designed to require or encourage explicit destruction in normal cases;
the preferred way to exit an application has always been to call exit.
We could have made things more convenient for the cases where a particular
kind of widget needs to be destroyed, but the current scheme of setting a
flag and writing your own event loop is not difficult to program and works
just fine.
-paul asente
asente@decwrl.dec.com decwrl!asente
ben@hpcvlx.cv.hp.com (Benjamin Ellsworth) (03/01/90)
Somebody condescended to give me the genesis of this thread. To quote The problem is that Joe Blow (whoever started this thread) wrote a widget that creates a 32 meg temp file. When applications exit with "exit(0);" the destroy callback for this widget is not called, and the file is not deleted. GOOD HEAVENS! Is THAT the problem???!!!! [ ...grumble, grumble... ] Every UN*X system that I've used allows the programmer to create a file, and then unlink it from the file system. As long as it is not closed, it exists known only by the program until it exits. (The Morris worm exploited this behavior.) When the program calls exit(), the system calls clean everything up very nicely. ---- Ben "It is a poor workman who blames his tools..."
rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (03/02/90)
If a widget consumes a resource that needs explicit freeing, the widget documentation had better document this so that the application can be sure to destroy the widget before exiting. This seems like bad design. I may have a Text widget today that doesn't do checkpoint files, so my documentation doesn't say it has to be destroyed, and the application believes this and blithely calls exit. Tomorrow I add checkpoint files, thinking this to be a nice addition from the user perspective, and suddenly I have to ask all developers to rewrite their applications? That doesn't sound like a very good design.
rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (03/02/90)
Every UN*X system that I've used allows the programmer to create a file, and then unlink it from the file system. This doesn't help for files that you *want* to stay around in the event of a crash.
ben@HPCVXBEN.CV.HP.COM (Benjamin Ellsworth) (03/02/90)
[This is getting ridiculous...] > > Every UN*X system that I've used allows the programmer to create a > file, and then unlink it from the file system. > > This doesn't help for files that you *want* to stay around in the > event of a crash. Very good Bob, but according to my source, Mr. Blow *wanted* a TEMP file. It was the fact that an *unwanted* file was left after a crash that started this whole thing. Had Mr. Blow been finding his widget to be leaving behind mega-bytes of useful data I'm sure that he would have never complained about file space consumption. Your comment seems a bit out of context. --- Ben
rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (03/02/90)
Very good Bob, but according to my source, Mr. Blow *wanted* a TEMP file. A text editor checkpoint file is a "TEMP" file, in my mind. Yes, there is a distinction between temp files that should or shouldn't survive a crash of the client, but they're both "temporary". It was the fact that an *unwanted* file was left after a crash that started this whole thing. No, it wasn't a *crash*, it was a normal termination of the client. The argument was that "normal" termination of a client should allow widgets to "clean up" in some fashion, yet the way most core clients exit doesn't permit this. This is entirely distinct from a crash, and bears directly on the distinction between the two classes of "temp" file. Your comment seems a bit out of context. I'm simply generalizing from the specific example to argue that the mechanism is inappropriate for a certain kind of widget state. And yes, Mr. Blow could probably solve his particular problem under a POSIX system, but Xt is supposed to be OS independent.
kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) (03/03/90)
> > > > Every UN*X system that I've used allows the programmer to create a > > file, and then unlink it from the file system. > > > > This doesn't help for files that you *want* to stay around in the > > event of a crash. > Very good Bob, but according to my source, Mr. Blow *wanted* a TEMP > file. It was the fact that an *unwanted* file was left after a crash > that started this whole thing. Had Mr. Blow been finding his widget to > be leaving behind mega-bytes of useful data I'm sure that he would have > never complained about file space consumption. Your comment seems a > bit out of context. Bob's message is an attempt to help people understand the more general problem. A problem that may be a design flaw in the Toolkit. I will try to state the general problem the we seem to have uncovered by thinging about how to solve the specific problem of the user. Problem: It is very difficult for an application writer to shutdown an Xt client cleanly. If she makes the assumption suggested by the originaly poster then widgets are the only ones who have enough information to clean up all their resources. The programmer must be sure that all widgets get destroyed before the application exits. The current Xt specification is unclear about whether or not this happens automatically when your call XtCloseDisplay, and XtDestroyApplicationContext. Paul has proposed that there is insuffecient mechanism in the toolkit to effeciently clean up these resources since there are really three types of widget resources: 1) Those that must always be cleaned up by the widget. 2) Those that will automatically be cleaned up by the operating system when the program exits. 3) Those that will be automatically cleaned up by the X Server when the display connection is closed, or the program exits. It seems that for optimal performance there are really three different kinds of widget cleanup that may occure. Solution: We have begun internal Consortium discussion on this topic, and will attempt to come up with a solution, but since this discussion is very preliminary I do not want to comment further in this public forum. Chris D. Peterson MIT X Consortium Net: kit@expo.lcs.mit.edu Phone: (617) 253 - 9608 Address: MIT - Room NE43-213
rlk@THINK.COM (Robert L. Krawitz) (03/05/90)
Date: 1 Mar 90 01:35:44 GMT From: hp-pcd!hpcvlx!ben@hplabs.hp.com (Benjamin Ellsworth) Every UN*X system that I've used allows the programmer to create a file, and then unlink it from the file system. As long as it is not closed, it exists known only by the program until it exits. (The Morris worm exploited this behavior.) When the program calls exit(), the system calls clean everything up very nicely. This doesn't work too well on NFS filesystems... ames >>>>>>>>> | Robert Krawitz <rlk@think.com> 245 First St. bloom-beacon > |think!rlk (postmaster) Cambridge, MA 02142 harvard >>>>>> . Thinking Machines Corp. (617)876-1111
ben@hpcvlx.cv.hp.com (Benjamin Ellsworth) (03/06/90)
>> [... open and unlink as a way to keep a hidden tmp file...] > > This doesn't work too well on NFS filesystems... I haven't used the approach across an NFS link. The SVID would lead on to believe that the approach should work regardless. IMO this reflects negatively on NFS (as do many other aspects of its implementation). Thanks for the warning. --- Ben
ben@hpcvlx.cv.hp.com (Benjamin Ellsworth) (03/06/90)
> I'm simply generalizing from the specific example to argue that the > mechanism is inappropriate for a certain kind of widget state. Thanks for the clarification. I hope that Mr. Blow is successful in his application, and I hope that the Intrinsics can enrichen their object model to provide for hygenic object destruction. Later, Ben
guy@auspex.auspex.com (Guy Harris) (03/07/90)
> Every UN*X system that I've used allows the programmer to create a > file, and then unlink it from the file system. As long as it is not > closed, it exists known only by the program until it exits. (The > Morris worm exploited this behavior.) When the program calls exit(), > the system calls clean everything up very nicely. > >This doesn't work too well on NFS filesystems... Gee, it works just fine on all the NFS filesystems *I've* used. The trick the NFS clients with which I'm familiar use is that instead of unlinking the file, they rename it to a temporary name, and when the last process on that client that has the file open closes it, they remove it. This works for the case of unlinking an open temporary file. (Yes, if the client machine crashes, the file doesn't get unlinked. The solution I've seen is to use a "find" script to remove files with names of the sort used as temporary names.)
gary@dgcad.SV.DG.COM (Gary Bridgewater) (03/07/90)
In article <9003042232.AA01692@underprize.think.com> rlk@THINK.COM (Robert L. Krawitz) writes: > > Date: 1 Mar 90 01:35:44 GMT > From: hp-pcd!hpcvlx!ben@hplabs.hp.com (Benjamin Ellsworth) > > Every UN*X system that I've used allows the programmer to create a > file, and then unlink it from the file system. As long as it is not > closed, it exists known only by the program until it exits. (The > Morris worm exploited this behavior.) When the program calls exit(), > the system calls clean everything up very nicely. > >This doesn't work too well on NFS filesystems... Whose? What rev? What fails? Scenario: open local file remove file do stuff with file system crashed data is gone Scenario: remote shell a program that opens a "local" file over "there" etc. Scenario: open file on NFS mounted disk remove file do stuff with file server crashes server comes up continue doing stuff with file exit {data may hang around in funny named file - cron cleans up} Scenario: open file on NFS mounted disk remove file do stuff with file "my" system crashes data is gone The difference with the NFS mounted file is that it gets renamed to a funny name instead of being instantly destroyed. It is gone in the sense that if you or anyone reopens the same original name it will not exist. How is this a problem? It is a bit of an inconvenience but, to our site, very much worth it. -- Gary Bridgewater, Data General Corporation, Sunnyvale California gary@sv.dg.com or {amdahl,aeras,amdcad}!dgcad!gary The impossible we understand right away - the obvious takes a little longer.