#include "main.h" #include #include #include #include #include #include #include #include #include namespace { bool killing = true; namespace handlers { void exit() { #if UF_ENV_DREAMCAST arch_stk_trace(1); #endif std::ofstream output; output.open(uf::io::root+"/logs/crash.txt"); for ( const auto& str : uf::iostream.getHistory() ) output << str << "\n"; output.close(); if ( client::terminated ) return; UF_MSG_INFO("Termination via std::atexit()!"); client::ready = false; //ext::ready = false; uf::ready = false; client::terminated = true; //ext::terminate(); uf::terminate(); client::terminate(); } void abrt( int sig ) { UF_MSG_ERROR("Abort detected"); #if UF_ENV_DREAMCAST arch_stk_trace(1); exit(); #else if ( ::killing ) { std::_Exit(0); } else if ( !client::terminated ) { ::killing = true; exit(); } #endif } void segv( int sig ) { UF_MSG_ERROR("Segfault detected"); #if UF_ENV_DREAMCAST arch_stk_trace(1); exit(); #else if ( ::killing ) { std::_Exit(0); } else if ( !client::terminated ) { ::killing = true; exit(); } #endif } } } int main(int argc, char** argv){ for ( size_t i = 0; i < argc; ++i ) { char* c_str = argv[i]; std::string string(argv[i]); uf::arguments.emplace_back(string); } std::atexit(::handlers::exit); signal(SIGABRT, ::handlers::abrt); signal(SIGSEGV, ::handlers::segv); client::initialize(); //ext::initialize(); uf::initialize(); // For Multithreaded initialization while ( !client::ready || !uf::ready ) { static uf::Timer timer(false); static double next = 1; if ( !timer.running() ) timer.start(); if ( timer.elapsed().asDouble() >= next ) { // UF_MSG_INFO("Waiting for " << ( client::ready ? "client" : "extension / engine" ) << " to initialize... Retrying in " << next << " seconds."); UF_MSG_INFO("Waiting for {} to initialize; retrying in {} seconds", ( client::ready ? "client" : "extension / engine" ), next); next *= 2; } } while ( client::ready && uf::ready ) { #if UF_EXCEPTIONS try { #endif if ( uf::renderer::settings::experimental::dedicatedThread /*&& !uf::renderer::states::rebuild*/ ) { // auto& thread = uf::thread::fetchWorker(); auto& thread = uf::thread::get("Render"); uf::thread::queue(thread, [&]{ //ext::render(); uf::render(); client::render(); }); client::tick(); //ext::tick(); uf::tick(); uf::thread::wait( thread ); } else { client::tick(); uf::tick(); //ext::tick(); //ext::render(); uf::render(); client::render(); } #if UF_EXCEPTIONS } catch ( std::runtime_error& e ) { UF_MSG_ERROR("RUNTIME ERROR: {}", e.what()); abort(); } catch ( std::exception& e ) { UF_MSG_ERROR("EXCEPTION ERROR: {}", e.what()); abort(); } catch ( bool handled ) { if (!handled) { UF_MSG_ERROR("UNHANDLED ERROR: {}", "???"); abort(); } } catch ( ... ) { UF_MSG_ERROR("UNKNOWN ERROR: {}", "???"); abort(); } #endif } if ( !client::terminated ) { client::terminated = true; UF_MSG_INFO("Natural termination!"); //ext::terminate(); uf::terminate(); client::terminate(); } return 0; }