| [ Return to Bugs & Features | Roadmap 1.1 | SVN ⇄ GIT ]
STR #679
Application: | FLTK Library |
Status: | 1 - Closed w/Resolution |
Priority: | 2 - Low, e.g. a documentation error or undocumented side-effect |
Scope: | 3 - Applies to all machines and operating systems |
Subsystem: | Core Library |
Summary: | hang if delete_widget on last widget |
Version: | 1.1.6 |
Created By: | jedimasterthrash |
Assigned To: | mike |
Fix Version: | 1.1.7 (SVN: v4388) |
Update Notification: | |
Trouble Report Files:
Trouble Report Comments:
|
#1 | jedimasterthrash 08:47 Dec 31, 2004 |
| I modified my code to use the new "delete_widget" function instead of doing "delete this" in the Close method. Luckily I'd previously made sure my destructors and not the Close methods were actually taking care of the close-stuff, so this was quite painless, and the delete_widget process appears to work very well.
Except for this one scenario. If you do a "delete_widget" on the last widget, the process hangs.
The window itself does close, which makes me think that the deletion actually took place. However, the process remains active (i.e., it still shows up in the task manager process list, and appears to be stuck in the fl::wait() loop somewhere).
It appears that forcing some windowing message can can break the hang. To demonstrate this, run it in debug mode, so that it has that console window always running in the background. After you do the close of the main window, and the window disappears, you see that the console window is still there, indiciating that fl::run() hasn't finished yet. But if you do an ALT-TAB to switch windows, the process finally exits.
I can't see the hang when stepping-through in debug mode, because the act of switching windows thus causes it to un-hang itself. But in release mode, without the extra console window, or debugging, the process remains active indefinitely.
My guess is that a bunch of messages keep showing up in the wait loop, preventing it from exiting. But I don't know where these messages are coming from.
I'm running XP pro & VS6 all the latest SPs and updates. Haven't tried on unix yet.
#include <FL/Fl.H> #include <FL/Fl_Double_Window.H>
class SpecialWindow : public Fl_Double_Window { public:
SpecialWindow(unsigned int w, unsigned int h) : Fl_Double_Window(w, h) { end(); callback(CloseCB, this); show(); } ~SpecialWindow() { hide(); } static void CloseCB(Fl_Widget *pW, void *pV) { Fl::delete_widget((SpecialWindow *)pV); } };
int main(int argc, char **argv) { SpecialWindow *pDW = new SpecialWindow(300, 300); return Fl::run(); } | |
|
#2 | mike 07:55 Feb 05, 2005 |
| I tested your program on Linux and was not able to reproduce the problem.
Can you add a Fl::check() call prior to calling Fl::delete_widget() to see if that resolves the problem?
| |
|
#3 | jedimasterthrash 20:39 Feb 12, 2005 |
| Adding the check() doesn't change anything, but I was able to narrow down the problem quite a bit.
The problem appears to be with the Fl_win32.cxx fl_wait() function, which probably explains why you don't see the problem in Linux.
The Fl::run()does a loop with Fl::wait(FOREVER), where FOREVER is really just 0x1e20
The first thing that wait() does is do the do_widget_deletion(). Fl_X::first correctly gets null'd after this. Then it calls fl_wait(time_to_wait).
What I discovered is that the length of time the process "hangs" is directly proportional to the time_to_wait
For instance, If I call wait(0), the process finishes immediately (no hang). If I call wait(1), the process hangs for just 1 second before finishing. If I call wait(10), the process hangs for just 10 seconds, etc.
I used MSVC's SPY++ to log all the messages going to this window while it was hanging. To my suprise, there were no messages. This means that win32 GetMessage was not being called, so my previous guess as to the cause was incorrect. But I did find this:
Here's the code in win32::fl_wait(): if (time_to_wait < 2147483.648) { // Perform the requested timeout... have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE); if (!have_message) { int t = (int)(time_to_wait * 1000.0 + .5); if (t <= 0) { // too short to measure fl_lock_function(); return 0; } timerid = SetTimer(NULL, 0, t, NULL); have_message = GetMessage(&fl_msg, NULL, 0, 0); KillTimer(NULL, timerid); } I don't know too much of how the internals of FLTK work, but it looks like after the last message is received, this code will set a timer and wait until the timer fires before completing. This means that when Fl::run() calls wait(FOREVER), it will set a timer for 1e20 seconds and "hang" until that timer fires. Or at least, that's what the symptoms seem to indicate.
Thanks, JMT.
| |
|
#4 | mike 05:34 Feb 14, 2005 |
| Hmm, looks like Windows isn't sending a message to the process when a window is deleted; perhaps we need to update the Fl_Window::hide() implementation to send a message on close?!?
| |
|
#5 | mike 05:45 Feb 14, 2005 |
| Fixed in Subversion repository. Try the attached patch and let me know if that doesn't fix things...
| |
|
#6 | jedimasterthrash 13:54 Feb 16, 2005 |
| Hmm. The fix doesn't seem to change anything. | |
|
#7 | mike 13:43 Feb 24, 2005 |
|
Does the problem only happen when you delete the last visible window, or ???
| |
|
#8 | Natevw 14:47 Feb 24, 2005 |
| If Fl::check() is added *after* the delete_widget() or hide() calls in JMT's example, the Fl::run() loop does exit properly after the last window is closed. Otherwise, I am getting similar results: it acts as if Fl::run() doesn't realize the last window has closed. HTH, -nate | |
|
#9 | jedimasterthrash 16:55 Feb 24, 2005 |
| Yep, it only hangs on the last window. | |
|
#10 | matt 02:18 Jun 01, 2005 |
| Fixed in Subversion repository. | |
[ Return to Bugs & Features ]
|
| |