Merge pull request #571 from jyrkive/fix-crash-on-openmp-relaunch
Fix some startup crashes
This commit is contained in:
commit
a34d036279
4 changed files with 90 additions and 26 deletions
|
@ -1211,6 +1211,9 @@
|
|||
[entry]
|
||||
name = "Justin DiSabatino (Turuk)"
|
||||
[/entry]
|
||||
[entry]
|
||||
name = "Jyrki Vesterinen"
|
||||
[/entry]
|
||||
[entry]
|
||||
name = "Kamil Kaczmarczyk (lampak)"
|
||||
[/entry]
|
||||
|
|
|
@ -675,7 +675,15 @@ std::string get_cwd()
|
|||
std::string get_exe_dir()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return get_cwd();
|
||||
wchar_t process_path[MAX_PATH];
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
GetModuleFileNameW(NULL, process_path, MAX_PATH);
|
||||
if (GetLastError() != ERROR_SUCCESS) {
|
||||
return get_cwd();
|
||||
}
|
||||
|
||||
path exe(process_path);
|
||||
return exe.parent_path().string();
|
||||
#else
|
||||
if (bfs::exists("/proc/")) {
|
||||
path self_exe("/proc/self/exe");
|
||||
|
|
|
@ -240,6 +240,12 @@ std::string &strip(std::string &str);
|
|||
/** Remove whitespace from the back of the string 'str'. */
|
||||
std::string &strip_end(std::string &str);
|
||||
|
||||
/** Surround the string 'str' with double quotes. */
|
||||
inline std::string quote(const std::string &str)
|
||||
{
|
||||
return '"' + str + '"';
|
||||
}
|
||||
|
||||
/** Convert no, false, off, 0, 0.0 to false, empty to def, and others to true */
|
||||
bool string_bool(const std::string& str,bool def=false);
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "serialization/binary_or_text.hpp" // for config_writer
|
||||
#include "serialization/parser.hpp" // for read
|
||||
#include "serialization/preprocessor.hpp" // for preproc_define, etc
|
||||
#include "serialization/string_utils.hpp"
|
||||
#include "serialization/validator.hpp" // for strict_validation_enabled
|
||||
#include "serialization/unicode_cast.hpp"
|
||||
#include "sound.hpp" // for commit_music_changes, etc
|
||||
|
@ -71,6 +72,7 @@
|
|||
#endif // _MSC_VER
|
||||
|
||||
#include <SDL.h> // for SDL_Init, SDL_INIT_TIMER
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp> // for auto_any_base, etc
|
||||
#include <boost/iostreams/categories.hpp> // for input, output
|
||||
#include <boost/iostreams/copy.hpp> // for copy
|
||||
|
@ -82,6 +84,7 @@
|
|||
#include <boost/scoped_ptr.hpp> // for scoped_ptr
|
||||
#include <boost/tuple/tuple.hpp> // for tuple
|
||||
|
||||
#include <algorithm> // for transform
|
||||
#include <cerrno> // for ENOMEM
|
||||
#include <clocale> // for setlocale, NULL, LC_ALL, etc
|
||||
#include <cstdio> // for remove, fprintf, stderr
|
||||
|
@ -90,6 +93,7 @@
|
|||
#include <exception> // for exception
|
||||
#include <fstream> // for operator<<, basic_ostream, etc
|
||||
#include <iostream> // for cerr, cout
|
||||
#include <vector>
|
||||
|
||||
//#define NO_CATCH_AT_GAME_END
|
||||
|
||||
|
@ -922,6 +926,40 @@ static void wesnoth_terminate_handler(int) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(_OPENMP) && _MSC_VER >= 1600
|
||||
static void restart_process(const std::vector<std::string>& commandline)
|
||||
{
|
||||
wchar_t process_path[MAX_PATH];
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
GetModuleFileNameW(NULL, process_path, MAX_PATH);
|
||||
if (GetLastError() != ERROR_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("Failed to retrieve the process path");
|
||||
}
|
||||
|
||||
std::wstring commandline_str = unicode_cast<std::wstring>(utils::join(commandline, " "));
|
||||
// CreateProcessW is allowed to modify the passed command line.
|
||||
// Therefore we need to copy it.
|
||||
wchar_t* commandline_c_str = new wchar_t[commandline_str.length() + 1];
|
||||
commandline_str.copy(commandline_c_str, commandline_str.length());
|
||||
commandline_c_str[commandline_str.length()] = L'\0';
|
||||
|
||||
STARTUPINFOW startup_info;
|
||||
ZeroMemory(&startup_info, sizeof(startup_info));
|
||||
startup_info.cb = sizeof(startup_info);
|
||||
PROCESS_INFORMATION process_info;
|
||||
ZeroMemory(&process_info, sizeof(process_info));
|
||||
|
||||
CreateProcessW(process_path, commandline_c_str, NULL, NULL,
|
||||
false, 0u, NULL, NULL, &startup_info, &process_info);
|
||||
|
||||
CloseHandle(process_info.hProcess);
|
||||
CloseHandle(process_info.hThread);
|
||||
|
||||
std::exit(EXIT_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__native_client__) || (defined(__APPLE__) && SDL_VERSION_ATLEAST(2, 0, 0))
|
||||
extern "C" int wesnoth_main(int argc, char** argv);
|
||||
int wesnoth_main(int argc, char** argv)
|
||||
|
@ -934,31 +972,6 @@ int main(int argc, char** argv)
|
|||
VLDEnable();
|
||||
#endif
|
||||
|
||||
#ifdef _OPENMP
|
||||
// Wesnoth is a special case for OMP
|
||||
// OMP wait strategy is to have threads busy-loop for 100ms
|
||||
// if there is nothing to do, they then go to sleep.
|
||||
// this avoids the scheduler putting the thread to sleep when work
|
||||
// is about to be available
|
||||
//
|
||||
// However Wesnoth has a lot of very small jobs that need to be done
|
||||
// at each redraw => 50fps every 2ms.
|
||||
// All the threads are thus busy-waiting all the time, hogging the CPU
|
||||
// To avoid that problem, we need to set the OMP_WAIT_POLICY env var
|
||||
// but that var is read by OMP at library loading time (before main)
|
||||
// thus the relaunching of ourselves after setting the variable.
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
if (!getenv("OMP_WAIT_POLICY")) {
|
||||
setenv("OMP_WAIT_POLICY", "PASSIVE", 1);
|
||||
execv(argv[0], argv);
|
||||
}
|
||||
#elif _MSC_VER >= 1600
|
||||
if (!getenv("OMP_WAIT_POLICY")) {
|
||||
_putenv_s("OMP_WAIT_POLICY", "PASSIVE");
|
||||
_execv(argv[0], argv);
|
||||
}
|
||||
#endif
|
||||
#endif //_OPENMP
|
||||
#ifdef _WIN32
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
@ -986,6 +999,34 @@ int main(int argc, char** argv)
|
|||
}
|
||||
#endif
|
||||
assert(!args.empty());
|
||||
|
||||
#ifdef _OPENMP
|
||||
// Wesnoth is a special case for OMP
|
||||
// OMP wait strategy is to have threads busy-loop for 100ms
|
||||
// if there is nothing to do, they then go to sleep.
|
||||
// this avoids the scheduler putting the thread to sleep when work
|
||||
// is about to be available
|
||||
//
|
||||
// However Wesnoth has a lot of very small jobs that need to be done
|
||||
// at each redraw => 50fps every 2ms.
|
||||
// All the threads are thus busy-waiting all the time, hogging the CPU
|
||||
// To avoid that problem, we need to set the OMP_WAIT_POLICY env var
|
||||
// but that var is read by OMP at library loading time (before main)
|
||||
// thus the relaunching of ourselves after setting the variable.
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
if (!getenv("OMP_WAIT_POLICY")) {
|
||||
setenv("OMP_WAIT_POLICY", "PASSIVE", 1);
|
||||
execv(argv[0], argv);
|
||||
}
|
||||
#elif _MSC_VER >= 1600
|
||||
if (!getenv("OMP_WAIT_POLICY")) {
|
||||
_putenv_s("OMP_WAIT_POLICY", "PASSIVE");
|
||||
args[0] = utils::quote(args[0]);
|
||||
restart_process(args);
|
||||
}
|
||||
#endif
|
||||
#endif //_OPENMP
|
||||
|
||||
if(SDL_Init(SDL_INIT_TIMER) < 0) {
|
||||
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
|
||||
return(1);
|
||||
|
@ -1021,6 +1062,12 @@ int main(int argc, char** argv)
|
|||
else if(filesystem::file_exists(exe_dir + "/../data/_main.cfg")) {
|
||||
auto_dir = filesystem::normalize_path(exe_dir + "/..");
|
||||
}
|
||||
// In Windows debug builds, the EXE is placed away from the game data dir
|
||||
// (in projectfiles\VCx\Debug), but the working directory is set to the
|
||||
// game data dir. Thus, check if the working dir is the game data dir.
|
||||
else if(filesystem::file_exists(filesystem::get_cwd() + "/data/_main.cfg")) {
|
||||
auto_dir = filesystem::get_cwd();
|
||||
}
|
||||
|
||||
if(!auto_dir.empty()) {
|
||||
std::cerr << "Automatically found a possible data directory at "
|
||||
|
|
Loading…
Add table
Reference in a new issue