Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Crash after closing wxMac with SFML-window  (Read 2535 times)

0 Members and 1 Guest are viewing this topic.

James.Harris

  • Newbie
  • *
  • Posts: 1
    • View Profile
Crash after closing wxMac with SFML-window
« on: January 21, 2019, 06:41:53 pm »
*System specification are as follow...
macOS Mojave -> Mac OS X 10.14.2
wxWidgets 3.1.2 -> --with-osx_cocoa --with-macosx-version-min=10.14 --with-macosx=MacOSX10.14.sdk
SFML 2.5.1 -> macOS OS X 10.7+, compatible with C++11 and libc++

The following code snippet, shown below, comes from a GitHub project that you can find at this link https://gist.github.com/eriknelson/e4ccf32534eb3d25a1ea. Please give Eriknelson credit for his SFML 2.3+ into wxWidgets 3.0 integration demo. This demo is not prefect but it only has one flaw. The application crashes after closing the wxWidgets window.

Code: [Select]
#include <iostream>
#include <wx/wx.h>
#include <memory>
#include <SFML/Graphics.hpp>

#ifdef __WXGTK__
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#endif

using namespace std;

static const int kDefaultWindowWidth = 1280;
static const int kDefaultWindowHeight = 720;
static const int kCanvasMargin = 0;

struct wxSfmlCanvas : public wxControl, public sf::RenderWindow
{
  wxSfmlCanvas(
    wxWindow *parent = nullptr,
    wxWindowID windowId = -1,
    const wxPoint &position = wxDefaultPosition,
    const wxSize &size = wxDefaultSize,
    long style = 0) :
  wxControl(parent, windowId, position, size, style)
  {
    createRenderWindow();
  }

  virtual void onUpdate(){};

  void onIdle(wxIdleEvent& event)
  {
    // Send a paint message when control is idle, to ensure max framerate
    Refresh();
  }

  void onPaint(wxPaintEvent& event)
  {
    wxPaintDC dc(this);     // Prepare control to be repainted
    onUpdate();             // Tick update
    display();              // Draw
  }

  // Explicitly overriding prevents wxWidgets from drawing, which could result in flicker
  void onEraseBackground(wxEraseEvent& event){}

  void createRenderWindow()
  {
#ifdef __WXGTK__
    // gtk_widget_realize(m_wxwindow);
    // gtk_widget_set_double_buffered(m_wxwindow, false);

    // GdkWindow *gdkWindow = gtk_widget_get_window((GtkWidget*)GetHandle());
    // XFlush(GDK_WINDOW_XDISPLAY(gdkWindow));

    // sf::RenderWindow::create(GDK_WINDOW_XWINDOW(gdkWindow));
#else
    sf::RenderWindow::create(GetHandle());
#endif
  }

  void setwxWindowSize(const wxSize& size)
  {
    this->SetSize(size);
  }

  void setRenderWindowSize(const sf::Vector2u& size)
  {
    this->setSize(size);
  }

  virtual ~wxSfmlCanvas(){};

wxDECLARE_EVENT_TABLE();
};

struct Canvas : public wxSfmlCanvas
{
  Canvas(
    wxWindow* parent,
    wxWindowID id,
    wxPoint position,
    wxSize size,
    long style = 0) :
  wxSfmlCanvas(parent, id, position, size, style)
  {
  }

  virtual void onUpdate()
  {
    clear(sf::Color::Yellow);
    sf::CircleShape shape(50);
    shape.setFillColor(sf::Color(150, 50, 250));
    shape.setOutlineThickness(10);
    shape.setOutlineColor(sf::Color(250, 150, 100));
    sf::RectangleShape line(sf::Vector2f(150, 5));
    line.rotate(45);
    this->draw(shape);
    this->draw(line);
  }

  void onResize(wxSizeEvent& event)
  {
    auto size = event.GetSize();
    auto newCanvasWidth = size.x - (2 * kCanvasMargin);
    auto newCanvasHeight = size.y - (2 * kCanvasMargin);
    sf::Vector2u v(newCanvasWidth,newCanvasHeight);
    wxSize s(newCanvasWidth,newCanvasHeight);
    this->SetSize(s); //wx setSize
    this->setSize(v); //SFML setSize
  }
};

struct AppFrame : public wxFrame
{
  AppFrame(const wxString& title, const wxPoint& pos, const wxSize& size) :
    wxFrame(NULL, wxID_ANY, title, pos, size),
    _panel(new wxPanel(this)),
    _canvas(new Canvas(
      _panel.get(),
      wxID_ANY,
      wxPoint(kCanvasMargin, kCanvasMargin),
      wxSize(kDefaultWindowWidth - (2 * kCanvasMargin), kDefaultWindowHeight - (2 * kCanvasMargin))
    ))
  {
    _panel->SetBackgroundColour(*wxCYAN);

    ////////////////////////////////////////////////////////////////////////////////
    // Probably due to some RTTI, IDE is getting confused by this dynamic call
    // and doesn't understand the correct Bind overload. Causes non sequitur errors
    // to display in the inspector. Suppress.
    //
    // Dynamic binding is cleanest here, since we don't want to hook up our resize
    // handler until our dependencies (Canvas namely) have finished their initialization
    ////////////////////////////////////////////////////////////////////////////////
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wint-conversion"
    Bind(wxEVT_SIZE, &AppFrame::onResize, this);
    #pragma clang diagnostic pop
    ////////////////////////////////////////////////////////////////////////////////

  }

  void onResize(wxSizeEvent& event)
  {
    _canvas->onResize(event);
    event.Skip();
  }

  unique_ptr<wxPanel> _panel;
  unique_ptr<Canvas> _canvas;
};

struct App : public wxApp
{
  virtual bool OnInit()
  {
    auto frame = new AppFrame("SFML Canvas Demo", wxPoint(100, 100),
                              wxSize(kDefaultWindowWidth, kDefaultWindowHeight));
    frame->Show(true);
    return true;
  }
};

wxBEGIN_EVENT_TABLE(wxSfmlCanvas, wxControl)
  EVT_IDLE(wxSfmlCanvas::onIdle)
  EVT_PAINT(wxSfmlCanvas::onPaint)
  EVT_ERASE_BACKGROUND(wxSfmlCanvas::onEraseBackground)
wxEND_EVENT_TABLE()

wxIMPLEMENT_APP(App);

His example runs as expected but upon closing the wxWidgets windows it crashes with the following error shown below.

Code: [Select]
rashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    Namespace OBJC, Code 0x1

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        0x00007fff64e7c01e __abort_with_payload + 10
1   libsystem_kernel.dylib        0x00007fff64e77541 abort_with_payload_wrapper_internal + 82
2   libsystem_kernel.dylib        0x00007fff64e774ef abort_with_reason + 22
3   libobjc.A.dylib                0x00007fff63c58674 _objc_fatalv(unsigned long long, unsigned long long, char const*, __va_list_tag*) + 108
4   libobjc.A.dylib                0x00007fff63c58526 _objc_fatal(char const*, ...) + 135
5   libobjc.A.dylib                0x00007fff63c62525 (anonymous namespace)::AutoreleasePoolPage::fastcheck(bool) + 125
6   libobjc.A.dylib                0x00007fff63c4a9f7 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 65
7   com.apple.CoreFoundation      0x00007fff37ab9ee6 _CFAutoreleasePoolPop + 22
8   com.apple.Foundation          0x00007fff39e66a5e -[NSAutoreleasePool drain] + 144
9   org.sfml-dev.sfml-window      0x000000010ffc86a5 drainThreadPool() + 37
10  org.sfml-dev.sfml-window      0x000000010ffc76e4 sf::priv::WindowImplCocoa::~WindowImplCocoa() + 148
11  org.sfml-dev.sfml-window      0x000000010ffc772f sf::priv::WindowImplCocoa::~WindowImplCocoa() + 15
12  org.sfml-dev.sfml-window      0x000000010ffb85ca sf::Window::~Window() + 58
13  org.wxwindows.                0x000000010fe8dc75 wxSfmlCanvas::~wxSfmlCanvas() + 37 (main.cpp:73)
14  org.wxwindows.                0x000000010fe8dc45 Canvas::~Canvas() + 21 (main.cpp:78)
15  org.wxwindows.                0x000000010fe8d505 Canvas::~Canvas() + 21 (main.cpp:78)
16  org.wxwindows.                0x000000010fe8d529 Canvas::~Canvas() + 25 (main.cpp:78)
17  org.wxwindows.                0x000000010fe8e740 AppFrame::~AppFrame() + 304 (memory:2285)
18  org.wxwindows.                0x000000010fe8b335 AppFrame::~AppFrame() + 21 (main.cpp:125)
19  org.wxwindows.                0x000000010fe8b359 AppFrame::~AppFrame() + 25 (main.cpp:125)
20  libwx_osx_cocoau-3.1.2.0.0.dylib 0x000000010fffdd3d wxAppConsoleBase::ProcessIdle() + 157
21  libwx_osx_cocoau-3.1.2.0.0.dylib 0x0000000110238476 wxAppBase::ProcessIdle() + 22
22  libwx_osx_cocoau-3.1.2.0.0.dylib 0x000000011018550a wxApp::ProcessIdle() + 26
23  libwx_osx_cocoau-3.1.2.0.0.dylib 0x00000001100e41fc wxCFEventLoop::OSXCommonModeObserverCallBack(__CFRunLoopObserver*, int, void*) + 92
24  com.apple.CoreFoundation      0x00007fff37b459cd __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
25  com.apple.CoreFoundation      0x00007fff37b45902 __CFRunLoopDoObservers + 452
26  com.apple.CoreFoundation      0x00007fff37ae7558 __CFRunLoopRun + 1469
27  com.apple.CoreFoundation      0x00007fff37ae6d48 CFRunLoopRunSpecific + 463
28  com.apple.HIToolbox            0x00007fff36d7dab5 RunCurrentEventLoopInMode + 293
29  com.apple.HIToolbox            0x00007fff36d7d7eb ReceiveNextEventCommon + 618
30  com.apple.HIToolbox            0x00007fff36d7d568 _BlockUntilNextEventMatchingListInModeWithFilter + 64
31  com.apple.AppKit              0x00007fff35038363 _DPSNextEvent + 997
32  com.apple.AppKit              0x00007fff35037102 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1362
33  com.apple.AppKit              0x00007fff35031165 -[NSApplication run] + 699
34  libwx_osx_cocoau-3.1.2.0.0.dylib 0x00000001101f0dff wxGUIEventLoop::OSXDoRun() + 207
35  libwx_osx_cocoau-3.1.2.0.0.dylib 0x00000001100e4ab1 wxCFEventLoop::DoRun() + 49
36  libwx_osx_cocoau-3.1.2.0.0.dylib 0x000000011002fcae wxEventLoopBase::Run() + 158
37  libwx_osx_cocoau-3.1.2.0.0.dylib 0x000000010fffda13 wxAppConsoleBase::MainLoop() + 99
38  libwx_osx_cocoau-3.1.2.0.0.dylib 0x000000011018555a wxApp::OnRun() + 26
39  libwx_osx_cocoau-3.1.2.0.0.dylib 0x0000000110067763 wxEntry(int&, wchar_t**) + 131
40  org.wxwindows.                0x000000010fe883b6 main + 38 (main.cpp:182)
41  libdyld.dylib                  0x00007fff64d24ed9 start + 1

Thread 1:
0   libsystem_pthread.dylib        0x00007fff64f173f8 start_wqthread + 0
1   ???                            0x0000000054485244 0 + 1414025796

Thread 2:: Dispatch queue: NSCGSDisableUpdates
0   libsystem_kernel.dylib        0x00007fff64e5e17a mach_msg_trap + 10
1   libsystem_kernel.dylib        0x00007fff64e5e6d0 mach_msg + 60
2   com.apple.SkyLight            0x00007fff5dc44bc5 CGSUpdateManager::enable_updates_common() + 577
3   com.apple.SkyLight            0x00007fff5dbe7e3b CGSUpdateManager::enable_update(unsigned long long) + 317
4   libdispatch.dylib              0x00007fff64cd5d53 _dispatch_call_block_and_release + 12
5   libdispatch.dylib              0x00007fff64cd6dcf _dispatch_client_callout + 8
6   libdispatch.dylib              0x00007fff64cdd124 _dispatch_lane_serial_drain + 618
7   libdispatch.dylib              0x00007fff64cddbdc _dispatch_lane_invoke + 388
8   libdispatch.dylib              0x00007fff64ce6090 _dispatch_workloop_worker_thread + 603
9   libsystem_pthread.dylib        0x00007fff64f1760b _pthread_wqthread + 409
10  libsystem_pthread.dylib        0x00007fff64f17405 start_wqthread + 13

Thread 3:
0   libsystem_pthread.dylib        0x00007fff64f173f8 start_wqthread + 0
1   ???                            0x0000000054485244 0 + 1414025796

Thread 4:: com.apple.NSEventThread
0   libsystem_kernel.dylib        0x00007fff64e5e17a mach_msg_trap + 10
1   libsystem_kernel.dylib        0x00007fff64e5e6d0 mach_msg + 60
2   com.apple.CoreFoundation      0x00007fff37ae80c2 __CFRunLoopServiceMachPort + 337
3   com.apple.CoreFoundation      0x00007fff37ae7611 __CFRunLoopRun + 1654
4   com.apple.CoreFoundation      0x00007fff37ae6d48 CFRunLoopRunSpecific + 463
5   com.apple.AppKit              0x00007fff35040f89 _NSEventThread + 160
6   libsystem_pthread.dylib        0x00007fff64f18305 _pthread_body + 126
7   libsystem_pthread.dylib        0x00007fff64f1b26f _pthread_start + 70
8   libsystem_pthread.dylib        0x00007fff64f17415 thread_start + 13

Thread 5:
0   libsystem_pthread.dylib        0x00007fff64f173f8 start_wqthread + 0

Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x0000000002000209  rbx: 0x0000000000000080  rcx: 0x00007ffedfd767c8  rdx: 0x0000000000000000
  rdi: 0x0000000000000008  rsi: 0x0000000000000001  rbp: 0x00007ffedfd76810  rsp: 0x00007ffedfd767c8
   r8: 0x00007febce519d50   r9: 0x0000000000000080  r10: 0x0000000000000000  r11: 0x0000000000000246
  r12: 0x0000000000000000  r13: 0x0000000000000000  r14: 0x0000000000000001  r15: 0x0000000000000008
  rip: 0x00007fff64e7c01e  rfl: 0x0000000000000246  cr2: 0x0000000116681000
 
Logical CPU:     0
Error Code:      0x02000209
Trap Number:     133

I suspect wxControl and sf::RenderWindows are trying the close the NSView, which comes from the GetHandle() call, at the same time. Before I start dissecting through wxWidgets and SFML source with a debugger, I would like to ask if anyone here have a solution for gracefully handling this scenario.

Meanwhile, I will be actively debugging this issue while this forum post is active. If I find a solution first, I will most definitely update this post with the solution as reference for all who have or will encounter this issue in the future.

-James Harris
« Last Edit: January 21, 2019, 06:46:53 pm by James.Harris »