in remote/main.cpp [116:264]
int main(int argc, char* argv[]) {
const boost::posix_time::ptime t0 = boost::posix_time::microsec_clock::local_time();
Log::setThreadName("main");
#if defined(OS_LINUX)
CefRefPtr<CefApp> cefApp = nullptr;
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromArgv(argc, argv);
const std::string& process_type = command_line->GetSwitchValue("type");
if (process_type == "renderer" || process_type == "zygote")
cefApp = new HelperApp();
// On Linux the zygote process is used to spawn other process types. Since
// we don't know what type of process it will be give it the renderer
// client.
CefMainArgs main_args(argc, argv);
int exit_code = CefExecuteProcess(main_args, cefApp, nullptr);
if (exit_code >= 0) {
return exit_code;
}
#elif WIN32
// Execute subprocess (if necessary)
CefRefPtr<CefApp> cefApp = nullptr;
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromString(::GetCommandLineW());
const std::string& process_type = command_line->GetSwitchValue("type");
const bool isMainBrowserProcess = process_type.empty();
if (!isMainBrowserProcess) {
// Initialize watchdog thread.
DWORD parentProcessPid = GetParentProcessPid();
HANDLE hParentProcess = OpenProcess(SYNCHRONIZE, FALSE, parentProcessPid);
std::thread([hParentProcess]() {
WaitForSingleObject(hParentProcess, INFINITE);
ExitProcess(0);
}).detach();
}
if (process_type == "renderer")
cefApp = new HelperApp();
CefMainArgs main_args(GetModuleHandle(0));
const int result = CefExecuteProcess(main_args, cefApp, nullptr);
if (result >= 0) {
// If CefExecuteProcess called for the browser process (identified by no "type" command-line value)
// it will return immediately with a value of -1.
return result;
}
#elif OS_MAC
initMacApplication();
#endif
const boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::local_time();
fprintf(stdout, "Starting cer server. Pre-initialize spent %d ms.\n", (int)(t1 - t0).total_milliseconds());
ServerApplication& app = ServerApplication::instance();
if (!app.init(argc, argv)) {
// Can't load CEF framework library.
return 100;
}
if (!getBoolEnv("CEF_SERVER_DONT_CATCH_SIGNALS")) {
setupCrashHandler();
}
const CommandLineArgs& cmdArgs = app.getCmdArgs();
#ifndef NDEBUG
if (cmdArgs.waitDebugger()) {
waitForDebug();
}
#endif
boost::posix_time::ptime t2 = boost::posix_time::microsec_clock::local_time();
Log::trace("Start CEF initialization. ServerApplication initialization spent %d ms.", (t2 - t1).total_milliseconds());
const bool success = CefUtils::initializeCef();
if (!success) {
Log::error("Cef initialization failed");
return 101;
}
if (!getBoolEnv("CEF_SERVER_DONT_CATCH_SIGNALS")) {
setupCrashHandler();
}
const boost::posix_time::ptime t3 = boost::posix_time::microsec_clock::local_time();
Log::trace("Create server transport. CEF initialization spent %d ms.", (t3 - t2).total_milliseconds());
std::shared_ptr<TServerTransport> serverTransport;
if (cmdArgs.useTcp()) {
serverTransport = std::make_shared<TServerSocket>("127.0.0.1", cmdArgs.getPort());
} else {
std::string pipePath = cmdArgs.getPipe();
if (pipePath.empty()) {
Log::error("Pipe path is empty, exit.");
return 102;
}
#ifdef WIN32
if (pipePath.rfind("\\\\.\\pipe\\", 0) != 0)
pipePath = "\\\\.\\pipe\\" + pipePath;
Log::info("Windows-pipe transport will be used, path=%s", pipePath.c_str());
serverTransport = std::make_shared<PipeTransportServer>(pipePath);
#else
std::remove(pipePath.c_str());
serverTransport = std::make_shared<TServerSocket>(pipePath.c_str());
#endif //WIN32
}
std::shared_ptr<apache::thrift::TProcessorFactory> processorFactory = app.getProcessorFactory();
std::shared_ptr<TThreadedServer> server = std::make_shared<TThreadedServer>(
processorFactory,
serverTransport,
std::make_shared<TBufferedTransportFactory>(),
std::make_shared<TBinaryProtocolFactory>());
const boost::posix_time::ptime t4 = boost::posix_time::microsec_clock::local_time();
Log::trace("Start listening thread. Transport initialization spent %d ms.", (t4 - t3).total_milliseconds());
std::thread servThread([=]() {
Log::setThreadName("ServerListener");
try {
server->serve();
} catch (TException& e) {
Log::error("Exception in listening thread");
Log::error(e.what());
} catch (...) {
Log::error("Unknown exception in listening thread");
}
Log::debug("Done, server stopped.");
});
const boost::posix_time::ptime t6 = boost::posix_time::microsec_clock::local_time();
Log::trace("Run CEF loop. Total initialization time %d ms.", (t6 - t0).total_milliseconds());
CefUtils::runCefLoop();
Log::debug("Finished message loop.");
server->stop();
servThread.join();
app.onBeforeExit();
#ifndef WIN32
if (!cmdArgs.useTcp())
std::remove(cmdArgs.getPipe().c_str());
#endif // WIN32
if (cmdArgs.deleteRootCacheDir() && !app.isDefaultRoot()) {
Log::debug("Remove root cache dir '%s'", app.getRootPath().c_str());
try {
std::filesystem::remove_all(app.getRootPath());
} catch (const std::filesystem::filesystem_error& ex) {
Log::error("Failed to remove root cache dir '%s'. Error: %s. Error code: %s", app.getRootPath().c_str(), ex.what(), ex.code().message().c_str());
}
}
Log::debug("Buy [%s]!", cmdArgs.getTransportDesc().c_str());
return 0;
}