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 { 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 #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 #endif
#if defined ARCH_WIN #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 #endif
#if defined ARCH_LIN #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 #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 #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 #endif
#if defined ARCH_MAC #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 #endif
#if defined ARCH_LIN #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(systemDir);
system::createDirectory(userDir); system::createDirectory(userDir);


+ 5
- 6
src/gamepad.cpp View File

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




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




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




static Driver driver;


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


void step() { void step() {
if (!driver)
return;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (glfwJoystickPresent(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(); startTime = system::getNanoseconds();
if (settings::devMode) { if (settings::devMode) {
outputFile = stderr; 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() { void init() {
// Don't re-initialize
if (!plugins.empty())
return;

// Load Core // Load Core
loadPlugin(""); loadPlugin("");


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


// For some reason this segfaults. // 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. // 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) if (!rootJ)
return; return;


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


json_dumpf(rootJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9)); 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) { void load(const std::string& path) {
INFO("Loading settings %s", path.c_str()); INFO("Loading settings %s", path.c_str());
FILE* file = fopen(path.c_str(), "r");
FILE* file = std::fopen(path.c_str(), "r");
if (!file) if (!file)
return; return;
DEFER({ DEFER({
fclose(file);
std::fclose(file);
}); });


json_error_t error; json_error_t error;


+ 7
- 6
src/updater.cpp View File

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




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

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






Loading…
Cancel
Save