axmolengine / axmol

Axmol Engine – A Multi-platform Engine for Desktop, XBOX (UWP) and Mobile games. (A fork of Cocos2d-x-4.0)
https://axmol.dev
MIT License
922 stars 205 forks source link

Yasio crash on Windows if used during static variable initialization #1784

Closed smilediver closed 7 months ago

smilediver commented 7 months ago

In our case this is triggered by Director::getInstance() getting called during static variable initialization stage. This causes a crash on Windows with the following stack:

shadergraphc.exe!yasio::inet::socket_select_interrupter::open_descriptors() Line 81 (c:\work\gms-playground-axmol\libs\axmol\3rdparty\yasio\yasio\impl\socket_select_interrupter.hpp:81)
shadergraphc.exe!yasio::inet::socket_select_interrupter::socket_select_interrupter() Line 28 (c:\work\gms-playground-axmol\libs\axmol\3rdparty\yasio\yasio\impl\socket_select_interrupter.hpp:28)
shadergraphc.exe!yasio::inet::poll_io_watcher::poll_io_watcher() Line 20 (c:\work\gms-playground-axmol\libs\axmol\3rdparty\yasio\yasio\impl\poll_io_watcher.hpp:20)
shadergraphc.exe!ax::Console::Console() Line 570 (c:\work\gms-playground-axmol\libs\axmol\core\base\Console.cpp:570)
shadergraphc.exe!ax::Director::init() Line 123 (c:\work\gms-playground-axmol\libs\axmol\core\base\Director.cpp:123)
shadergraphc.exe!ax::Director::getInstance() Line 101 (c:\work\gms-playground-axmol\libs\axmol\core\base\Director.cpp:101)
...

The crash happens in code bellow, because bind returns -1 and then exception is thrown:

    int retval = acceptor.bind(ep);
    if (retval < 0)
      yasio__throw_error(xxsocket::get_last_errno(), "socket_select_interrupter");

Last error value is 10093, because WSAStartup() was not called yet.

So there are two issues:

A workaround would be to delay initialization for Console like bellow, but this would only hide the actual issue of yasio not calling WSAStartup and Console crashing on socket issues.

    _scheduler->runOnAxmolThread([this]() {
        _console = new Console;
    });
halx99 commented 7 months ago

I guess you invoke Director::getInstance before main function which is not good code practice.