#19196: wxMessageBox called from PAINT_EVENT handler crashes the program

47 views
Skip to first unread message

wxTrac

unread,
Jun 5, 2021, 1:59:55 PM6/5/21
to wx-...@googlegroups.com
#19196: wxMessageBox called from PAINT_EVENT handler crashes the program
------------------------------+--------------------
Reporter: RohitAgarwal33 | Owner:
Type: defect | Status: new
Priority: normal | Milestone:
Component: GUI-all | Version: 3.0.5
Keywords: OSX 11.1 M1 chip | Blocked By:
Blocking: | Patch: 0
------------------------------+--------------------
To debug drawing code, I use a message box from the handler for the paint-
event.
This crashes the program.
If I use a message box from any other context it works fine.
Could be something to do with the paint event handler locking the graphics
context.
Since the message box is a dialog, I assume it runs in its own thread,
so this should not be the expected behaviour.

I am running BigSur 11.1 on a MacMini M1

--
Ticket URL: <https://trac.wxwidgets.org/ticket/19196>

wxTrac

unread,
Jun 5, 2021, 5:32:55 PM6/5/21
to wx-...@googlegroups.com
#19196: wxMessageBox called from PAINT_EVENT handler crashes the program
-----------------------------+--------------------
Reporter: RohitAgarwal33 | Owner:
Type: defect | Status: closed
Priority: normal | Milestone:
Component: GUI-all | Version: 3.0.5
Resolution: invalid | Keywords:
Blocked By: | Blocking:
Patch: 0 |
-----------------------------+--------------------
Changes (by vadz):

* status: new => closed
* keywords: OSX 11.1 M1 chip =>
* resolution: => invalid


Comment:

The program crashes due to `wxEVT_PAINT` handler reentrancy because you
keep showing message boxes as you're getting paint events while the
message box is shown. You can avoid it in several ways, e.g. by using
`wxLogXXX()` functions instead or using `CallAfter()` explicitly, but
there is no way to prevent user code from crashing due to this reentrancy
in general, unfortunately, so you do need to take care.

--
Ticket URL: <https://trac.wxwidgets.org/ticket/19196#comment:1>

rohit agarwal

unread,
Jun 5, 2021, 9:08:22 PM6/5/21
to wx-...@googlegroups.com
The code is structured in such a way
that the message box is called only when a specific part of the code initiates a paint
by calling RefreshRect and Update.
Therefore, only one paint message arrives and causes a crash.
> --
> You received this message because you are subscribed to the Google Groups "wx-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to wx-dev+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/wx-dev/053.d8f1ca5d64f5ebc4fc03f706879d6e20%40wxwiki.org.

Igor Korot

unread,
Jun 5, 2021, 9:22:22 PM6/5/21
to wx-dev
Hi,



On Sat, Jun 5, 2021, 8:08 PM rohit agarwal <hex-...@khitchdee.net> wrote:
The code is structured in such a way
that the message box is called only when a specific part of the code initiates a paint
by calling RefreshRect and Update.
Therefore, only one paint message arrives and causes a crash.

Please re-read what Vadim said.
You can't use wxMessageBox from EVT_PAINT.

Use wxLogXXX().

Thank you.

rohit agarwal

unread,
Jun 6, 2021, 4:47:33 AM6/6/21
to wx-...@googlegroups.com
If there was a non-modal version of, or alternative to, wxMessageBox,
that would serve to solve this minor workaround.
For now, logging or CallAfter() are both acceptable workarounds.
> --
> You received this message because you are subscribed to the Google Groups "wx-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to wx-dev+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/wx-dev/068.f6dab27b222c6372b3d7ebb7f8c72366%40wxwiki.org.

Vadim Zeitlin

unread,
Jun 6, 2021, 9:25:46 AM6/6/21
to wx-...@googlegroups.com
On Sun, 6 Jun 2021 06:38:13 +0530 rohit agarwal wrote:

ra> The code is structured in such a way
ra> that the message box is called only when a specific part of the code initiates a paint
ra> by calling RefreshRect and Update.
ra> Therefore, only one paint message arrives and causes a crash.

You didn't mention this in your original report, so it was hard to guess.
If you really already protect against reentrancies and still crash, I don't
know why does it happen and would need to have a way of reproducing the
problem (ideally, with a minimal patch to one of the samples, as explained
in https://trac.wxwidgets.org/wiki/HowToSubmitTicket) or, at the very
least, the stack at the moment of the crash.

Regards,
VZ

rohit agarwal

unread,
Jun 6, 2021, 10:05:40 AM6/6/21
to wx-...@googlegroups.com
I’ll prepare a minimal patch to one of the samples.

I do believe the crash should happen,
since the wxMessageBox is a modal dialog and grabs focus after it is launched.
Doing so from inside the paint-evt handler which probably locks the DC for itself
means the (modal) dialog is in confllct for this resource.
If the dialog were non-modal then there would not be a conflict
since it would be a separate window with its own thread and timing.

wxTrac

unread,
Jun 6, 2021, 12:32:37 PM6/6/21
to wx-...@googlegroups.com
#19196: wxMessageBox called from PAINT_EVENT handler crashes the program
-----------------------------+--------------------
Reporter: RohitAgarwal33 | Owner:
Type: defect | Status: closed
Priority: normal | Milestone:
Component: GUI-all | Version: 3.0.5
Resolution: invalid | Keywords:
Blocked By: | Blocking:
Patch: 0 |
-----------------------------+--------------------

Comment (by csomor):

I also think that putting a dialog in a drawRect handler might natively
not be supported

--
Ticket URL: <https://trac.wxwidgets.org/ticket/19196#comment:2>

wxTrac

unread,
Jun 6, 2021, 8:46:04 PM6/6/21
to wx-...@googlegroups.com
#19196: wxMessageBox called from PAINT_EVENT handler crashes the program
-----------------------------+--------------------
Reporter: RohitAgarwal33 | Owner:
Type: defect | Status: closed
Priority: normal | Milestone:
Component: GUI-all | Version: 3.0.5
Resolution: invalid | Keywords:
Blocked By: | Blocking:
Patch: 0 |
-----------------------------+--------------------
Changes (by RohitAgarwal33):

* Attachment "bug-test.cpp" added.

To demo wxMessage in wxEVT_APINT handler crash

wxTrac

unread,
Jun 6, 2021, 8:47:55 PM6/6/21
to wx-...@googlegroups.com
#19196: wxMessageBox called from PAINT_EVENT handler crashes the program
-----------------------------+--------------------
Reporter: RohitAgarwal33 | Owner:
Type: defect | Status: closed
Priority: normal | Milestone:
Component: GUI-all | Version: 3.0.5
Resolution: invalid | Keywords:
Blocked By: | Blocking:
Patch: 0 |
-----------------------------+--------------------
Changes (by RohitAgarwal33):

* cc: rohit@… (added)


Comment:

I'm attaching a file named bug-test.cpp
After building it and running

it shows on the screen: "press space bar"
if you press space bar, it shows: "you pressed space bar, press escape to
exit"
press escape to exit.

If you uncomment line 82 the wxMessageBox in response to the user action
in
the wxEVT_PAINT handler causes the program to exit.

Code pasted below:


#include "wx/wxprec.h"
#include "wx/wx.h"

int g_scrnH, g_scrnW;
bool g_bUsrActn = false;

class MyCanvas;
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
MyCanvas *m_canvas;
private:
};

class MyApp : public wxApp
{
public:
virtual bool OnInit() wxOVERRIDE;
virtual int OnExit() wxOVERRIDE { return 0; }
};
wxIMPLEMENT_APP(MyApp);

class MyCanvas : public wxWindow
{
public:
MyCanvas( MyFrame *parent, wxSize size );
void OnPaint(wxPaintEvent &event);
void OnKeyDown(wxKeyEvent &event);
private:
MyFrame *m_owner;
wxDECLARE_EVENT_TABLE();
};

wxBEGIN_EVENT_TABLE(MyCanvas, wxWindow)
EVT_PAINT (MyCanvas::OnPaint)
EVT_KEY_DOWN (MyCanvas::OnKeyDown)
wxEND_EVENT_TABLE()


bool MyApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;

g_scrnW = wxSystemSettings::GetMetric(wxSYS_SCREEN_X,NULL);
g_scrnH = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y,NULL)-20;

MyFrame *frame = new MyFrame("hex-draw", wxPoint(0,0), wxSize(g_scrnW,
g_scrnH));
frame->Show(true);
frame->ShowFullScreen(true, wxFULLSCREEN_NOSTATUSBAR );
return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize&
size)
: wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size)
{
EnableFullScreenView();
m_canvas = new MyCanvas( this, size );
}

MyCanvas::MyCanvas(MyFrame *parent, wxSize size )
: wxWindow(parent, wxID_ANY, wxPoint( 0, 0 ), size )
{
m_owner = parent;
}

void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
{
wxPaintDC *pdc = new wxPaintDC(this);
int width, height;

// check if it's the intro or a response to a user action
if( !g_bUsrActn )
{
pdc->DrawText("press space bar", g_scrnW/2, g_scrnH/2);
}
else // its a response to a user action
{
pdc->DrawText("you pressed space bar, press escape to exit",
g_scrnW/2, g_scrnH/2);
// wxMessageBox( "in wxEVT_PAINT
handler",wxMessageBoxCaptionStr,wxOK|wxCENTRE,NULL,wxDefaultCoord,wxDefaultCoord
);
}
return;
}

void MyCanvas::OnKeyDown(wxKeyEvent &event)
{
int keyCode = event.GetKeyCode();
g_bUsrActn = true;

switch( keyCode )
{
case 27:
m_owner->Close( true );
break;
case 32:
g_bUsrActn = true;
Refresh( true, NULL );
Update();
break;
default:
break;
}
return;
}

--
Ticket URL: <https://trac.wxwidgets.org/ticket/19196#comment:3>

wxTrac

unread,
Jun 6, 2021, 9:14:27 PM6/6/21
to wx-...@googlegroups.com
#19196: wxMessageBox called from PAINT_EVENT handler crashes the program
-----------------------------+--------------------
Reporter: RohitAgarwal33 | Owner:
Type: defect | Status: closed
Priority: normal | Milestone:
Component: GUI-all | Version: 3.0.5
Resolution: invalid | Keywords:
Blocked By: | Blocking:
Patch: 0 |
-----------------------------+--------------------
Changes (by RohitAgarwal33):

* cc: rohit@… (removed)


Comment:

Here's the CallAfter() workaround (it works)

void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
{
wxPaintDC *pdc = new wxPaintDC(this);
int width, height;

// check if it's the intro or a response to a user action
if( !g_bUsrActn )
{
pdc->DrawText("press space bar", g_scrnW/2, g_scrnH/2);
}
else // its a response to a user action
{
pdc->DrawText("you pressed space bar, press escape to exit",
g_scrnW/2, g_scrnH/2);
wxGetApp().CallAfter([]{
wxMessageBox( "in wxEVT_PAINT
handler",wxMessageBoxCaptionStr,wxOK|wxCENTRE,NULL,wxDefaultCoord,wxDefaultCoord
);
});
}

--
Ticket URL: <https://trac.wxwidgets.org/ticket/19196#comment:4>

wxTrac

unread,
Jun 9, 2021, 8:47:53 AM6/9/21
to wx-...@googlegroups.com
#19196: wxMessageBox called from PAINT_EVENT handler crashes the program
-----------------------------+--------------------
Reporter: RohitAgarwal33 | Owner:
Type: defect | Status: closed
Priority: normal | Milestone:
Component: GUI-all | Version: 3.0.5
Resolution: invalid | Keywords:
Blocked By: | Blocking:
Patch: 0 |
-----------------------------+--------------------

Comment (by vadz):

Thanks, but there is a lot of extra code here and it's not clear if it's
really needed or not. E.g. do you need to show the frame full screen for
this to happen? Do you need to call `Update()` from `OnKeyDown()`?

--
Ticket URL: <https://trac.wxwidgets.org/ticket/19196#comment:5>

rohit agarwal

unread,
Jun 9, 2021, 9:08:51 AM6/9/21
to wx-...@googlegroups.com
Fullscreen makes the message handling in wx_EVT_PAINT handler a lot more deterministic.
The update is extra.
This is a minimal version of my own app derived from the drawing sample
Sorry.
> --
> You received this message because you are subscribed to the Google Groups "wx-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to wx-dev+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/wx-dev/068.1fae9b0122475deca8eae5adcc5f6494%40wxwiki.org.

Eric Jensen

unread,
Jun 9, 2021, 11:58:21 AM6/9/21
to rohit agarwal
Hello rohit,

Wednesday, June 9, 2021, 3:08:45 PM, you wrote:

ra> Fullscreen makes the message handling in wx_EVT_PAINT handler a lot more deterministic.
ra> The update is extra.
ra> This is a minimal version of my own app derived from the drawing sample
ra> Sorry.

Isn't this all very academic?

I can't think of any scenario where it makes sense to have any user interaction during a paint event. A paint event handler should be completely "passive" and just draw "a state". Anything that requires user interaction should be known and dealt with outside the paint event handler.

Just my 2 cents.

Eric


rohit agarwal

unread,
Jun 9, 2021, 7:42:38 PM6/9/21
to wx-...@googlegroups.com
Hello Eric,

I think I’m covered there.
I said in the origional bug submission on trac
that this is for debugging drawing code.
You can check to verify.
It’s not academic but developer-related
and not production but debugging related.

Rohit
> --
> You received this message because you are subscribed to the Google Groups "wx-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to wx-dev+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/wx-dev/72279014.20210609175820%40j-dev.de.

Reply all
Reply to author
Forward
0 new messages