dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Do you have a typical platform dependent issue you're battling with ? Ask it here. Make sure you mention your platform, compiler, and wxWidgets version.
Post Reply
jerome_mao
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Jul 18, 2016 6:02 am

dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by jerome_mao »

wxClientDC dc; dc.GetSize(&w,&h) have assertion on linux OS when app run in debug mode,release mode is ok;(3.0.2 version)
It beacause the canvas refresh before parent window show. if we don't change the function, how we fixed this bug? It is ok in wx2.8.12 version;

frame-> canvas(panel)
void Canvas::drawBackup()
{
wxClientDC dc(this);
int w,h;
dc.GetSize(&w,&h); //assertion
....
}
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by DavidHart »

Hi,
dc.GetSize() crash...
dc.GetSize(&w,&h) have assertion...
Which is it, a crash or assert?

wx3 added lots of asserts that show unless you define NDEBUG. If that's all that is happening you can just ignore the asserts or prevent them in that way. Or if they are gtk+ critical warnings, those can almost always be ignored.

Actual crashes are different ;) . One thing you can do is to Bind() wxIdleEvents. In the handler check the size of the parent window; if it's e.g. 20x20 that means the window isn't shown. Once it gets to a sensible size, Unbind() wxIdleEvents and switch on Canvas::drawBackup.

Regards,

David
User avatar
flederwiesel
Earned a small fee
Earned a small fee
Posts: 17
Joined: Fri Apr 14, 2017 3:01 pm
Location: Germany
Contact:

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by flederwiesel »

Hi everybody,
I have a similar, if not the same issue. The code works fine on Windows using MinGW, however debugging under Linux leads to a trap:

Code: Select all

// can't use assert here to avoid infinite loops, so just trap
wxTrap();
I think this is an issue to be reported, however, I would like you to cross-check before I would finally report a bug. Maybe it's just me...
Please find attached code of a screensaver I did, stripped down to the bone, but still leading to the trap.

Environment:

Code: Select all

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 8.10 (jessie)
Release:	8.10
Codename:	jessie

$ wx-config --version-full
3.0.4.0

$ pkg-config gtk+-2.0 --modversion
2.24.25

$ pkg-config gtk+-2.0 --version
0.28
Stack trace:

Code: Select all

0  0x00007ffff566075b  raise  /build/glibc-6V9RKT/glibc-2.19/nptl/../nptl/sysdeps/unix/sysv/linux/pt-raise.c  37
1  0x00007ffff610c6ba  wxTrap  .../wxWidgets-v3.0.4/src/common/appbase.cpp  1054
2  0x00007ffff610c762  wxDefaultAssertHandler  .../wxWidgets-v3.0.4/src/common/appbase.cpp  1081
3  0x00007ffff610d0f6  wxOnAssert  .../wxWidgets-v3.0.4/src/common/appbase.cpp  1182
4  0x00007ffff6befee4  wxWindowDCImpl::DoGetSize  .../wxWidgets-v3.0.4/src/gtk/dcclient.cpp  451
5  0x000000000040d20d  wxDC::GetSize  /usr/include/wx-3.0/wx/dc.h  815
6  0x000000000040adb7  SaverContent::OnSize  .../saver/content.cpp  32
7  0x00007ffff610b5e1  wxAppConsoleBase::HandleEvent  .../wxWidgets-v3.0.4/src/common/appbase.cpp  611
8  0x00007ffff610b654  wxAppConsoleBase::CallEventHandler  .../wxWidgets-v3.0.4/src/common/appbase.cpp  623
9  0x00007ffff621da3e  wxEvtHandler::ProcessEventIfMatchesId  .../wxWidgets-v3.0.4/src/common/event.cpp  1390
10  0x00007ffff621c7f1  wxEventHashTable::HandleEvent  .../wxWidgets-v3.0.4/src/common/event.cpp  996
11  0x00007ffff621df3d  wxEvtHandler::TryHereOnly  .../wxWidgets-v3.0.4/src/common/event.cpp  1587
12  0x00007ffff621f87d  wxEvtHandler::TryBeforeAndHere  .../wxWidgets-v3.0.4/include/wx/event.h  3671
13  0x00007ffff621dd63  wxEvtHandler::ProcessEventLocally  .../wxWidgets-v3.0.4/src/common/event.cpp  1520
14  0x00007ffff621dcfb  wxEvtHandler::ProcessEvent  .../wxWidgets-v3.0.4/src/common/event.cpp  1493
15  0x00007ffff621dfed  wxEvtHandler::SafelyProcessEvent  .../wxWidgets-v3.0.4/src/common/event.cpp  1611
16  0x00007ffff6d78ed8  wxWindowBase::HandleWindowEvent  .../wxWidgets-v3.0.4/src/common/wincmn.cpp  1525
17  0x00007ffff6be446f  wxWindow::DoSetSize  .../wxWidgets-v3.0.4/src/gtk/window.cpp  2937
18  0x00007ffff6bdb3c8  wxWindowBase::SetSize  .../wxWidgets-v3.0.4/include/wx/window.h  266
19  0x00007ffff6d6d66e  wxTopLevelWindowBase::DoLayout  .../wxWidgets-v3.0.4/src/common/toplvcmn.cpp  425
20  0x00007ffff6d6de7a  wxTopLevelWindowBase::OnSize  .../wxWidgets-v3.0.4/include/wx/toplevel.h  283
21  0x00007ffff610b5e1  wxAppConsoleBase::HandleEvent  .../wxWidgets-v3.0.4/src/common/appbase.cpp  611
22  0x00007ffff610b654  wxAppConsoleBase::CallEventHandler  .../wxWidgets-v3.0.4/src/common/appbase.cpp  623
23  0x00007ffff621da3e  wxEvtHandler::ProcessEventIfMatchesId  .../wxWidgets-v3.0.4/src/common/event.cpp  1390
24  0x00007ffff621c7f1  wxEventHashTable::HandleEvent  .../wxWidgets-v3.0.4/src/common/event.cpp  996
25  0x00007ffff621df3d  wxEvtHandler::TryHereOnly  .../wxWidgets-v3.0.4/src/common/event.cpp  1587
26  0x00007ffff621f87d  wxEvtHandler::TryBeforeAndHere  .../wxWidgets-v3.0.4/include/wx/event.h  3671
27  0x00007ffff621dd63  wxEvtHandler::ProcessEventLocally  .../wxWidgets-v3.0.4/src/common/event.cpp  1520
28  0x00007ffff621dcfb  wxEvtHandler::ProcessEvent  .../wxWidgets-v3.0.4/src/common/event.cpp  1493
29  0x00007ffff621dfed  wxEvtHandler::SafelyProcessEvent  .../wxWidgets-v3.0.4/src/common/event.cpp  1611
30  0x00007ffff6d78ed8  wxWindowBase::HandleWindowEvent  .../wxWidgets-v3.0.4/src/common/wincmn.cpp  1525
31  0x00007ffff6d77b24  wxWindowBase::SendSizeEvent  .../wxWidgets-v3.0.4/src/common/wincmn.cpp  1106
32  0x00007ffff6bda778  wxTopLevelWindowGTK::GTKUpdateDecorSize  .../wxWidgets-v3.0.4/src/gtk/toplevel.cpp  1405
33  0x00007ffff6bd7cf2  property_notify_event  .../wxWidgets-v3.0.4/src/gtk/toplevel.cpp  532
34  0x00007ffff4d8ca3f  ??    
35  0x00007ffff3617245  g_closure_invoke    
36  0x00007ffff3628f6c  ??    
37  0x00007ffff3631285  g_signal_emit_valist    
38  0x00007ffff36319df  g_signal_emit    
39  0x00007ffff4ea3d0c  ??    
40  0x00007ffff4d8b77b  gtk_main_do_event    
41  0x00007ffff49feb6c  ??    
42  0x00007ffff2c58c5d  g_main_context_dispatch    
43  0x00007ffff2c58f48  ??    
44  0x00007ffff2c59272  g_main_loop_run    
45  0x00007ffff4d13ca3  gtk_dialog_run    
46  0x00007ffff6bdbb3f  wxGUIAppTraits::ShowAssertDialog  .../wxWidgets-v3.0.4/src/gtk/utilsgtk.cpp  329
47  0x00007ffff610d59a  ShowAssertDialog  .../wxWidgets-v3.0.4/src/common/appbase.cpp  1306
48  0x00007ffff610bcab  wxAppConsoleBase::OnAssertFailure  .../wxWidgets-v3.0.4/src/common/appbase.cpp  785
49  0x00007ffff6bb14d9  wxApp::OnAssertFailure  .../wxWidgets-v3.0.4/src/gtk/app.cpp  540
50  0x00007ffff610c87e  wxDefaultAssertHandler  .../wxWidgets-v3.0.4/src/common/appbase.cpp  1097
51  0x00007ffff610d0f6  wxOnAssert  .../wxWidgets-v3.0.4/src/common/appbase.cpp  1182
52  0x00007ffff6befee4  wxWindowDCImpl::DoGetSize  .../wxWidgets-v3.0.4/src/gtk/dcclient.cpp  451
53  0x000000000040d20d  wxDC::GetSize  /usr/include/wx-3.0/wx/dc.h  815
54  0x000000000040adb7  SaverContent::OnSize  .../saver/content.cpp  32
55  0x00007ffff610b5e1  wxAppConsoleBase::HandleEvent  .../wxWidgets-v3.0.4/src/common/appbase.cpp  611
56  0x00007ffff610b654  wxAppConsoleBase::CallEventHandler  .../wxWidgets-v3.0.4/src/common/appbase.cpp  623
57  0x00007ffff621da3e  wxEvtHandler::ProcessEventIfMatchesId  .../wxWidgets-v3.0.4/src/common/event.cpp  1390
58  0x00007ffff621c7f1  wxEventHashTable::HandleEvent  .../wxWidgets-v3.0.4/src/common/event.cpp  996
59  0x00007ffff621df3d  wxEvtHandler::TryHereOnly  .../wxWidgets-v3.0.4/src/common/event.cpp  1587
60  0x00007ffff621f87d  wxEvtHandler::TryBeforeAndHere  .../wxWidgets-v3.0.4/include/wx/event.h  3671
61  0x00007ffff621dd63  wxEvtHandler::ProcessEventLocally  .../wxWidgets-v3.0.4/src/common/event.cpp  1520
62  0x00007ffff621dcfb  wxEvtHandler::ProcessEvent  .../wxWidgets-v3.0.4/src/common/event.cpp  1493
63  0x00007ffff621dfed  wxEvtHandler::SafelyProcessEvent  .../wxWidgets-v3.0.4/src/common/event.cpp  1611
64  0x00007ffff6d78ed8  wxWindowBase::HandleWindowEvent  .../wxWidgets-v3.0.4/src/common/wincmn.cpp  1525
65  0x00007ffff6be446f  wxWindow::DoSetSize  .../wxWidgets-v3.0.4/src/gtk/window.cpp  2937
66  0x000000000040fb10  wxWindowBase::SetSize  /usr/include/wx-3.0/wx/window.h  266
67  0x000000000040ec24  SaverContainer::SaverContainer  .../saver/container.cpp  74
68  0x0000000000410390  MainApp::OnInit  .../saver/main.cpp  26
69  0x00000000004104c9  wxAppConsoleBase::CallOnInit  /usr/include/wx-3.0/wx/app.h  93
70  0x00007ffff6178d05  wxEntry  .../wxWidgets-v3.0.4/src/common/init.cpp  490
71  0x00007ffff6178df8  wxEntry  .../wxWidgets-v3.0.4/src/common/init.cpp  518
72  0x000000000041030c  main  .../saver/main.cpp  18
@DavidHart: Regarding your answer:
- Why would I define _NDEBUG, as debugging is exactly what I want to do now?
- Usually asserts have a meaning and usually give a hint that something goes wrong (even if somewhere else and not in your code). So ignoring them is bad advice IMHO
- Further advising to
Bind() wxIdleEvents
seems to be a bad hack. Correct me, if I am wrong, but as a wx newbie, I would not even know how to do this, and this would be overkill for a very simple application. I'd expect newbies to be discouraged by this....

Regards,
Tobias
Attachments
saver.7z
(5.45 KiB) Downloaded 82 times
* DEFINITION: Computer - A device designed to speed and automate errors.
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by DavidHart »

Hi,
- Why would I define _NDEBUG, as debugging is exactly what I want to do now?
Then you wouldn't. But the OP may have been complaining about assert spam, rather than trying to debug.
- Usually asserts have a meaning and usually give a hint that something goes wrong (even if somewhere else and not in your code). So ignoring them is bad advice IMHO
The asserts I was thinking of are not due to your code, but caused by wxWidgets or gtk+ internals and are often very multiple; so not something the user will want to see.
- Further advising to Bind() wxIdleEvents seems to be a bad hack
It's not perfect, but it works around issues where the wxWidgets thinks a control is properly created and sized, but (iiuc) the underlying toolkit hasn't quite got round to doing it yet. A bit like yours...

I got the same issue on testing your code (debian stretch). The Bind() 'hack' prevented it happening, but isn't necessary in your case. Instead I found it was enough just to split almost all the contents of SaverContainer::SaverContainer into a separate method that I've called ActuallyCreate().

Code: Select all

bool MainApp::OnInit()
{
	SaverContainer *saver = NULL;

	try
	{
		saver = new SaverContainer();
		saver->ActuallyCreate();
	}
	catch (...)
	{
	}

	return saver ? true : false;
}

SaverContainer::SaverContainer() :
	wxTopLevelWindow(NULL, 0, wxT("fra-airtraffic"))
{
#if defined(__WXMSW__)
	SetIcon(wxIcon(wxT("ApplicationIcon")));
#endif

#ifndef _DEBUG
	hideCursor();
#endif
}

void SaverContainer::ActuallyCreate()
{
  int xmin, xmax;
	int ymin, ymax;
	unsigned int m;
	unsigned int monitors;
	SaverContent *content;
	wxRect rect;

	xmin = xmax =
	ymin = ymax = 0;

	monitors = wxDisplay::GetCount();

	for (m = 0; m < monitors; m++)
	{
		rect = wxDisplay(m).GetGeometry();

		if (xmin > rect.x)
			xmin = rect.x;

		if (xmax < rect.x + rect.width)
			xmax = rect.x + rect.width;

		if (ymin > rect.y)
			ymin = rect.y;

		if (ymax < rect.y + rect.height)
			ymax = rect.y + rect.height;
	}

  // This operates on one display only
  ShowFullScreen(true);
  // Expand to virtual screens

  for (unsigned int m = wxDisplay::GetCount(); m < monitors; m++)
  {
    rect = wxDisplay(m).GetGeometry();

    content = new SaverContent(this);

    // As xmin/ymin may have a negative value, we need to
    // respect this when positioning the client windows
    if (content)
      content->SetSize(rect.x - xmin, rect.y - ymin, rect.width, rect.height);
  }
}
Regards,

David
User avatar
flederwiesel
Earned a small fee
Earned a small fee
Posts: 17
Joined: Fri Apr 14, 2017 3:01 pm
Location: Germany
Contact:

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by flederwiesel »

David,
thanks for your reply and coding the workaround so quickly. Tested it and no asserts appear.

However (I don't want to be ungrateful), as you pointed out, with gtk not having done its work yet, this is a quite confusing scenario - after all I called the wxWindow constructor and would expect the window to be ready to go. Isn't this something wxWidget should take care of? I am not familiar with gtk, and one reason for choosing was portability without having to care what goes on underneath...

So would you agree we have an issue here??

Thanks,
Tobias
* DEFINITION: Computer - A device designed to speed and automate errors.
User avatar
flederwiesel
Earned a small fee
Earned a small fee
Posts: 17
Joined: Fri Apr 14, 2017 3:01 pm
Location: Germany
Contact:

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by flederwiesel »

Hmm,
re-checked the code, and now it is clear why the assertions disappeared:

Code: Select all

   monitors = wxDisplay::GetCount();
    ...
-for (m = 0; m < monitors; m++)
+for (unsigned int m = wxDisplay::GetCount(); m < monitors; m++)
{
    rect = wxDisplay(m).GetGeometry();

    content = new SaverContent(this);

        content->SetSize(rect.x - xmin, rect.y - ymin, rect.width, rect.height);
We never get to the last line - this is where we got into the trap...
* DEFINITION: Computer - A device designed to speed and automate errors.
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by DavidHart »

after all I called the wxWindow constructor and would expect the window to be ready to go. Isn't this something wxWidget should take care of?
It would be nice if it could. However the problem has been there 'forever'. I'm sure the wx devs would have fixed it long ago if it were possible.
re-checked the code, and now it is clear why the assertions disappeared...
My apologies. I played around with the code, and that was a left-over that I failed to notice. With that fixed I get the same assert as you, and continue to get it whether I delay the sizing code calls as above or, to my surprise, using wxEVT_IDLE. I tried changing to using wxFrame and wxPanel as the base-classes instead of wxTopLevelWindow and wxWindow (which are rarely used direct) again without success.

I also unsuccessfully tried wxSafeYield(), as suggested in viewtopic.php?t=39128.

So I'm afraid I don't have a fix for you. I can only suggest you remove any non-essential sizing code, and try to make sure that what remains is not called early.
User avatar
flederwiesel
Earned a small fee
Earned a small fee
Posts: 17
Joined: Fri Apr 14, 2017 3:01 pm
Location: Germany
Contact:

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by flederwiesel »

Looks like I have to dive into gtk, I'm afraid. Should I have the time and find something out, I'll let you know.

Regards,
Tobias
* DEFINITION: Computer - A device designed to speed and automate errors.
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by doublemax »

I assume this is the code that causes the assert?

Code: Select all

wxWindowDC dc(this);
dc.GetSize(&cx, &cy);
There are at least two easy ways to avoid this.

1) Don't use wxWindowDC. As you only need the size, use GetClientSize().

2) Use wxDC::IsOk() to check if its save to use.
Use the source, Luke!
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by DavidHart »

Looks like I have to dive into gtk, I'm afraid.
I don't recommend that. Not only is it non-trivial to access gtk+2 code direct from wx and probably wouldn't help, it's unlikely to be needed.

If you look at the samples that come with the wx source, you'll see that many of them make SetSize() or SetClientSize() calls. Yet they don't (usually ;) ) assert or crash. I realise that your code is trying to do something different, but nevertheless you may find you can morph one of the samples ('minimal'? 'erase'?) to make it do what you want. And, as a bonus, that code will be more likely to work in a gtk+3 build too, or running on Wayland instead of X11.
User avatar
flederwiesel
Earned a small fee
Earned a small fee
Posts: 17
Joined: Fri Apr 14, 2017 3:01 pm
Location: Germany
Contact:

Re: dc.GetSize() crash on linux OS with wxwidgets 3.0.2 version( debug mode)

Post by flederwiesel »

Thank you for the feedback.

@doublemax:
Don't use wxWindowDC
The code is a couple of months old already, so I hope I remember correctly: When writing this, I had trouble painting on multiple monitors, each in fullscreen mode. Maybe there is a better solution, but this is what I finally got to work on MSW at the time - after all it is my first wx project. If you want to have a look at the whole thing in context (but you don't have to), see https://github.com/flederwiesel/fra-airtraffic.

@DavidHart:
I don't recommend that.
I mean just for understanding what's going on. Never thought of using gtk directly from within my program.

Right now I don't have the time to investigate further, however, I will try to look into the wxWindowDC thing as soon as I can.

Regards,
Tobias.
* DEFINITION: Computer - A device designed to speed and automate errors.
Post Reply