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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - James.Harris

Pages: [1]
1
C / 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

Pages: [1]