Browse Source

Make all environment init() functions re-entrant after calling destroy() if it exists.

tags/v2.0.0
Andrew Belt 5 years ago
parent
commit
b6f1191168
6 changed files with 107 additions and 94 deletions
  1. +79
    -71
      src/asset.cpp
  2. +5
    -6
      src/gamepad.cpp
  3. +6
    -5
      src/logger.cpp
  4. +6
    -2
      src/plugin.cpp
  5. +4
    -4
      src/settings.cpp
  6. +7
    -6
      src/updater.cpp

+ 79
- 71
src/asset.cpp View File

@@ -28,91 +28,99 @@ namespace rack {
namespace asset {


void init() {
// Get system dir
if (systemDir.empty()) {
if (settings::devMode) {
systemDir = ".";
}
else {
static void initSystemDir() {
if (systemDir != "")
return;

if (settings::devMode) {
systemDir = ".";
return;
}

#if defined ARCH_MAC
CFBundleRef bundle = CFBundleGetMainBundle();
assert(bundle);
// Check if we're running as a command-line program or an app bundle.
CFURLRef bundleUrl = CFBundleCopyBundleURL(bundle);
// Thanks Ken Thomases! https://stackoverflow.com/a/58369256/272642
CFStringRef uti;
if (CFURLCopyResourcePropertyForKey(bundleUrl, kCFURLTypeIdentifierKey, &uti, NULL) && uti && UTTypeConformsTo(uti, kUTTypeApplicationBundle)) {
char bundleBuf[PATH_MAX];
Boolean success = CFURLGetFileSystemRepresentation(bundleUrl, TRUE, (UInt8*) bundleBuf, sizeof(bundleBuf));
assert(success);
bundlePath = bundleBuf;
}
CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(bundle);
char resourcesBuf[PATH_MAX];
Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8*) resourcesBuf, sizeof(resourcesBuf));
assert(success);
CFRelease(resourcesUrl);
systemDir = resourcesBuf;
CFBundleRef bundle = CFBundleGetMainBundle();
assert(bundle);
// Check if we're running as a command-line program or an app bundle.
CFURLRef bundleUrl = CFBundleCopyBundleURL(bundle);
// Thanks Ken Thomases! https://stackoverflow.com/a/58369256/272642
CFStringRef uti;
if (CFURLCopyResourcePropertyForKey(bundleUrl, kCFURLTypeIdentifierKey, &uti, NULL) && uti && UTTypeConformsTo(uti, kUTTypeApplicationBundle)) {
char bundleBuf[PATH_MAX];
Boolean success = CFURLGetFileSystemRepresentation(bundleUrl, TRUE, (UInt8*) bundleBuf, sizeof(bundleBuf));
assert(success);
bundlePath = bundleBuf;
}
CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(bundle);
char resourcesBuf[PATH_MAX];
Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8*) resourcesBuf, sizeof(resourcesBuf));
assert(success);
CFRelease(resourcesUrl);
systemDir = resourcesBuf;
#endif
#if defined ARCH_WIN
// Get path to executable
wchar_t moduleBufW[MAX_PATH];
DWORD length = GetModuleFileNameW(NULL, moduleBufW, LENGTHOF(moduleBufW));
assert(length > 0);
// Get folder of executable
PathRemoveFileSpecW(moduleBufW);
// Convert to short path to avoid Unicode
wchar_t moduleBufShortW[MAX_PATH];
GetShortPathNameW(moduleBufW, moduleBufShortW, LENGTHOF(moduleBufShortW));
systemDir = string::fromWstring(moduleBufShortW);
// Get path to executable
wchar_t moduleBufW[MAX_PATH];
DWORD length = GetModuleFileNameW(NULL, moduleBufW, LENGTHOF(moduleBufW));
assert(length > 0);
// Get folder of executable
PathRemoveFileSpecW(moduleBufW);
// Convert to short path to avoid Unicode
wchar_t moduleBufShortW[MAX_PATH];
GetShortPathNameW(moduleBufW, moduleBufShortW, LENGTHOF(moduleBufShortW));
systemDir = string::fromWstring(moduleBufShortW);
#endif
#if defined ARCH_LIN
// Users should launch Rack from their terminal in the system directory
systemDir = ".";
// Users should launch Rack from their terminal in the system directory
systemDir = ".";
#endif
}
}


static void initUserDir() {
if (userDir != "")
return;

if (settings::devMode) {
userDir = ".";
return;
}

// Get user dir
if (userDir.empty()) {
if (settings::devMode) {
userDir = ".";
}
else {
#if defined ARCH_WIN
// Get "My Documents" folder
wchar_t documentsBufW[MAX_PATH] = L".";
HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufW);
assert(result == S_OK);
// Convert to short path to avoid Unicode
wchar_t documentsBufShortW[MAX_PATH];
GetShortPathNameW(documentsBufW, documentsBufShortW, LENGTHOF(documentsBufShortW));
userDir = string::fromWstring(documentsBufShortW);
userDir += "/Rack";
// Get "My Documents" folder
wchar_t documentsBufW[MAX_PATH] = L".";
HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufW);
assert(result == S_OK);
// Convert to short path to avoid Unicode
wchar_t documentsBufShortW[MAX_PATH];
GetShortPathNameW(documentsBufW, documentsBufShortW, LENGTHOF(documentsBufShortW));
userDir = string::fromWstring(documentsBufShortW);
userDir += "/Rack";
#endif
#if defined ARCH_MAC
// Get home directory
struct passwd* pw = getpwuid(getuid());
assert(pw);
userDir = pw->pw_dir;
userDir += "/Documents/Rack";
// Get home directory
struct passwd* pw = getpwuid(getuid());
assert(pw);
userDir = pw->pw_dir;
userDir += "/Documents/Rack";
#endif
#if defined ARCH_LIN
// Get home directory
const char* homeBuf = getenv("HOME");
if (!homeBuf) {
struct passwd* pw = getpwuid(getuid());
assert(pw);
homeBuf = pw->pw_dir;
}
userDir = homeBuf;
userDir += "/.Rack";
#endif
}
// Get home directory
const char* homeBuf = getenv("HOME");
if (!homeBuf) {
struct passwd* pw = getpwuid(getuid());
assert(pw);
homeBuf = pw->pw_dir;
}
userDir = homeBuf;
userDir += "/.Rack";
#endif
}

void init() {
initSystemDir();
initUserDir();

system::createDirectory(systemDir);
system::createDirectory(userDir);


+ 5
- 6
src/gamepad.cpp View File

@@ -12,7 +12,6 @@ struct Driver;


static const int DRIVER = -10;
static Driver* driver = NULL;


struct InputDevice : midi::InputDevice {
@@ -117,17 +116,17 @@ struct Driver : midi::Driver {
};


static Driver driver;


void init() {
driver = new Driver;
midi::addDriver(DRIVER, driver);
midi::addDriver(DRIVER, &driver);
}

void step() {
if (!driver)
return;
for (int i = 0; i < 16; i++) {
if (glfwJoystickPresent(i)) {
driver->devices[i].step();
driver.devices[i].step();
}
}
}


+ 6
- 5
src/logger.cpp View File

@@ -18,12 +18,13 @@ void init() {
startTime = system::getNanoseconds();
if (settings::devMode) {
outputFile = stderr;
return;
}
else {
outputFile = std::fopen(asset::logPath.c_str(), "w");
if (!outputFile) {
std::fprintf(stderr, "Could not open log at %s\n", asset::logPath.c_str());
}
assert(!outputFile);
outputFile = std::fopen(asset::logPath.c_str(), "w");
if (!outputFile) {
std::fprintf(stderr, "Could not open log at %s\n", asset::logPath.c_str());
}
}



+ 6
- 2
src/plugin.cpp View File

@@ -203,6 +203,10 @@ static void extractPackages(std::string path) {
////////////////////

void init() {
// Don't re-initialize
if (!plugins.empty())
return;

// Load Core
loadPlugin("");

@@ -239,13 +243,13 @@ void init() {
void destroy() {
for (Plugin* plugin : plugins) {
// Free library handle
if (plugin->handle) {
#if defined ARCH_WIN
if (plugin->handle)
FreeLibrary((HINSTANCE) plugin->handle);
#else
if (plugin->handle)
dlclose(plugin->handle);
#endif
}

// For some reason this segfaults.
// It might be best to let them leak anyway, because "crash on exit" issues would occur with badly-written plugins.


+ 4
- 4
src/settings.cpp View File

@@ -249,11 +249,11 @@ void save(const std::string& path) {
if (!rootJ)
return;

FILE* file = fopen(path.c_str(), "w");
FILE* file = std::fopen(path.c_str(), "w");
if (!file)
return;
DEFER({
fclose(file);
std::fclose(file);
});

json_dumpf(rootJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9));
@@ -262,11 +262,11 @@ void save(const std::string& path) {

void load(const std::string& path) {
INFO("Loading settings %s", path.c_str());
FILE* file = fopen(path.c_str(), "r");
FILE* file = std::fopen(path.c_str(), "r");
if (!file)
return;
DEFER({
fclose(file);
std::fclose(file);
});

json_error_t error;


+ 7
- 6
src/updater.cpp View File

@@ -48,12 +48,13 @@ static void checkVersion() {


void init() {
if (!settings::devMode) {
std::thread t([] {
checkVersion();
});
t.detach();
}
if (settings::devMode)
return;

std::thread t([]() {
checkVersion();
});
t.detach();
}




Loading…
Cancel
Save