Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!mips!pacbell.com!att!ucbvax!bloom-beacon!dont-send-mail-to-path-lines From: swick@athena.mit.EDU (Ralph Swick) Newsgroups: comp.windows.x Subject: Re: XtDestroyWidget bug?/problem/question Message-ID: <9104022146.AA10493@lyre.MIT.EDU> Date: 2 Apr 91 21:46:32 GMT References: <9103222135.AA03192@madison.ivy.isc.com> Sender: daemon@athena.mit.edu (Mr Background) Organization: The Internet Lines: 111 The problem routine in question is XtDestroyWidget. The test case that I've appended to the end of this program (from a customer) generates and then destroys a widget tree in a forever loop. You need to re-read section 2.8 of the Xt spec (page 690 of the Digital Press book). The widget destruction and the freeing of associated resources does not take place until the very final stage of XtDispatchEvent. The reason for this is that the callback in which XtDestroyWidget was invoked may not be the last one in the callback list and remaining callbacks need to be permitted to reference the widget whose destruction is pending. Among other things, this permits widgets to destroy themselves from within callbacks. This means that if an event dispatch invokes a callback procedure that never returns (as in your example), phase 2 of the destruction never occurs for widgets destroyed in this dispatch (stack) frame. Modifying your example as follows will make it work as you expect: *** original **** --- fixed ---- *************** *** 130,138 **** #include /* common XToolkit definitions */ #include /* common widget definitions */ #include ! #include ! #include ! #include #define MULTI /* #define UNREALIZE */ --- 132,140 ---- #include /* common XToolkit definitions */ #include /* common widget definitions */ #include ! #include ! #include ! #include #define MULTI /* #define UNREALIZE */ *************** *** 211,225 **** system("ps -el | grep X"); } ! void DoCreateDestroyI(w, client_data, call_data) ! Widget w; ! caddr_t client_data; ! caddr_t call_data; { ! bCancelI = False; ! createdestroyCount = 0; ! ! while (!bCancelI) { if (!(createdestroyCount % 10)) { fprintf(stderr, "CreateDestroy count = %d\n", createdestroyCount); system("/etc/swap -l"); --- 213,224 ---- system("ps -el | grep X"); } ! void TimerCreateDestroy(client_data, id) ! XtPointer client_data; ! XtIntervalId id; { ! Widget w = (Widget)client_data; ! if (!bCancelI) { if (!(createdestroyCount % 10)) { fprintf(stderr, "CreateDestroy count = %d\n", createdestroyCount); system("/etc/swap -l"); *************** *** 226,235 **** system("ps -el | grep xswap"); system("ps -el | grep X"); } ! DoCreateDestroy(w, client_data, call_data); createdestroyCount++; UpdateScreenNow(w); } } void DoCreateDestroy(w, client_data, call_data) --- 225,248 ---- system("ps -el | grep xswap"); system("ps -el | grep X"); } ! DoCreateDestroy((Widget)client_data, NULL, NULL); createdestroyCount++; UpdateScreenNow(w); + XtAppAddTimeOut(XtWidgetToApplicationContext(w), 1, + TimerCreateDestroy, client_data); } + } + + void DoCreateDestroyI(w, client_data, call_data) + Widget w; + caddr_t client_data; + caddr_t call_data; + { + bCancelI = False; + createdestroyCount = 0; + + XtAppAddTimeOut(XtWidgetToApplicationContext(w), 1, + TimerCreateDestroy, (XtPointer)w); } void DoCreateDestroy(w, client_data, call_data)