| [ Return to Bugs & Features | Roadmap 1.1 | SVN ⇄ GIT ]
STR #685
Application: | FLTK Library |
Status: | 1 - Closed w/Resolution |
Priority: | 3 - Moderate, e.g. unable to compile the software |
Scope: | 3 - Applies to all machines and operating systems |
Subsystem: | Core Library |
Summary: | Fl_Menu::popup()/pulldown() can crash if Fl_Group::current() set |
Version: | 1.1.6 |
Created By: | mike |
Assigned To: | mike |
Fix Version: | 1.1.7 |
Update Notification: | |
Trouble Report Files:
Trouble Report Comments:
|
#1 | mike 06:58 Jan 04, 2005 |
| Posted by Greg Ercolano on fltk.bugs:
The following documents a problem where an app with a 'right click menu' will crash if the user navigates the popup menu while the app is manipulating unrelated widgets at the same time (eg. via a timer)
I've canned an example where there's a widget hierarchy:
Fl_Window | |-- Fl_Menu_Button -- popup menu |-- Fl_Scroll -- scroll (clear()'ed and rebuilt every second by a timer) |-- Fl_Box |-- Fl_Box |-- Fl_Box
Seems if the scroll is clear()ed and rebuilt while the popup menu is posted, the user can no longer navigate the popup menu; submenus either post offscreen, or in random positions.. the app crashes soon after.
I'm pretty sure the problem is the popup menu's submenus are somehow loosing track of who its parent widget because of the concurrent manipulation of the unrelated Fl_Scroll widget happening off the timer at the same time.
Seems like a reentrancy problem with the popup menu code? Maybe it's dependent on the begin()/end() stuff, or some other global.
Thought I'd post this to fltk.bugs before making an STR, in case it's something I'm doing wrong in the code.
Here's the GDB crash output:
* * * (gdb) run Starting program: /usr/local/src/fltk-1.1.6/test/foo --- tick --- tick --- tick --- tick --- tick
Program received signal SIGSEGV, Segmentation fault. 0x0806cf0c in typeinfo for Fl_Single_Window () (gdb) where #0 0x0806cf0c in typeinfo for Fl_Single_Window () #1 0x08057a90 in Fl_Label::draw(int, int, int, int, Fl_Align) const () #2 0x08057c01 in Fl_Widget::draw_label(int, int, int, int, Fl_Align) const () #3 0x0804d7ca in Fl_Group::draw_outside_label(Fl_Widget const&) const () #4 0x0804d626 in Fl_Group::draw_children() () #5 0x0805231e in Fl_Window::draw() () #6 0x0804c42e in Fl_Window::flush() () #7 0x0804b509 in Fl::flush() () #8 0x0804b203 in Fl::wait(double) () #9 0x0804b302 in Fl::run() () #10 0x0804ae14 in main () #11 0x42015504 in __libc_start_main () from /lib/tls/libc.so.6 * * *
Here's the program that demonstrates the problem, tested with 1.1.6 / redhat 9.
To replicate: post the main menu by right clicking, then while the popup menu is posted, wait for the display to change, then navigate to a submenu.. weird behavior ensues.
Release the right button, and move the mouse off the window to achieve the crash. Can replicate every time.
* * * #include <stdio.h> #include <stdlib.h> #include <FL/Fl.H> #include <FL/Fl_Window.H> #include <FL/Fl_Scroll.H> #include <FL/Fl_Box.H> #include <FL/Fl_Menu_Button.H>
#define XRES 600 #define YRES 400
Fl_Window *G_win = 0; Fl_Scroll *G_scroll = 0;
static void Rebuild() { G_scroll->clear(); // clear previous
// CREATE RANDOM NUMBER OF BOXES EACH TIME G_scroll->begin(); for ( int y=30, t=1; t<((rand()%10)+5); t++, y+=35) { Fl_Box *b = new Fl_Box(30,y,XRES-40,30); b->box(FL_FLAT_BOX); b->color(FL_BLUE); } G_scroll->end(); G_win->redraw(); }
static void Timer_CB(void *) { fprintf(stderr, "--- tick\n"); Rebuild(); Fl::repeat_timeout(1.0, Timer_CB); }
int main() { // WINDOW WITH SCROLL G_win = new Fl_Window(XRES,YRES); G_scroll = new Fl_Scroll(10,10,XRES-20,YRES-20); G_scroll->box(FL_FLAT_BOX); Rebuild();
// ADD POPUP MENU TO WINDOW G_win->begin(); Fl_Menu_Button popup(0,0,XRES,YRES); popup.type(Fl_Menu_Button::POPUP3); popup.add("File/Open"); popup.add("File/Save"); popup.add("Edit/Copy"); popup.add("Edit/Paste"); G_win->end();
// TIMER TO REBUILD INTERFACE PERIODICALLY Fl::add_timeout(1.0, Timer_CB); // comment out to prevent coredump G_win->resizable(G_scroll); G_win->show(); return(Fl::run()); }
....
Followup:
Narrowed it down to just Fl_Group::current() changing while the popup menu is open.
It seems that calling begin() and end() leaves current() changed.
If I save the value of current() in the timer routine before calling begin(), then restore it after calling end(), then the app doesn't crash, and the popup behaves normally.
Also, I can simplify the program down to where the timer routine /just/ invokes begin() and end() to cause the crash. eg:
---- #include <FL/Fl.H> #include <FL/Fl_Window.H> #include <FL/Fl_Menu_Button.H>
Fl_Window *G_win = 0;
static void Timer_CB(void *) { G_win->begin(); // changes Fl::current(), causes crash Fl::repeat_timeout(1.0, Timer_CB); }
int main() { G_win = new Fl_Window(600,400); Fl_Menu_Button popup(0,0,600,400); popup.type(Fl_Menu_Button::POPUP3); popup.add("File/Open"); popup.add("Edit/Copy"); Fl::add_timeout(1.0, Timer_CB); G_win->show(); return(Fl::run()); } ---- | |
|
#2 | mike 07:01 Jan 04, 2005 |
| Appears to be an issue with Fl::release() being called after the fakemenu widget is deleted.
Solution (patch attached) is to release before deleting... | |
[ Return to Bugs & Features ]
|
| |