1
0
mirror of https://github.com/fuse-friends/fuse-native synced 2024-10-27 18:34:01 +00:00
fuse-friends_fuse-native/abstractions.cc
Jan Kühle 8769284245 Fix possible deadlock because of never unlocked mutex during failed unmount (#31)
* Fix possible deadlock because of never unlocked mutex during failed unmount.

* Fix segmentation fault after unmounting.

Scenario:
1. Mount path /a
2. Mount path /b
3. Unmount path /b
4. Appempt to read from path /a will throw segmentation fault.

Reason:
The function bindings_alloc correctly allocates memory and sets the index property of the binding. Afterwards the mount function does memset again for the binding and resets the index to zero. Unmounting will now always NULL the binding at position zero. However the actual binding on position zero is still mounted and the next access to it results in segmentation fault.
2016-10-17 13:50:38 +02:00

114 lines
2.7 KiB
C++

#include "abstractions.h"
#ifndef _WIN32
#include <unistd.h>
#include <sys/wait.h>
int execute_command_and_wait (char* argv[]) {
// Fork our running process.
pid_t cpid = vfork();
// Check if we are the observer or the new process.
if (cpid > 0) {
int status = 0;
waitpid(cpid, &status, 0);
return WIFEXITED(status) ? WEXITSTATUS(status) : -1;
} else {
// At this point we are on our child process.
execvp(argv[0], argv);
exit(1);
// Something failed.
return -1;
}
}
#endif
#ifdef __APPLE__
#include <unistd.h>
#include <sys/wait.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void thread_create (abstr_thread_t* thread, thread_fn fn, void* data) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(thread, &attr, fn, data);
}
void thread_join (abstr_thread_t thread) {
pthread_join(thread, NULL);
}
int fusermount (char *path) {
char *argv[] = {(char *) "umount", path, NULL};
return execute_command_and_wait(argv);
}
#elif defined(_WIN32)
HANDLE mutex = CreateMutex(NULL, false, NULL);
void thread_create (HANDLE* thread, thread_fn fn, void* data) {
*thread = CreateThread(NULL, 0, fn, data, 0, NULL);
}
void thread_join (HANDLE thread) {
WaitForSingleObject(thread, INFINITE);
}
int fusermount (char *path) {
char* dokanPath = getenv("DOKAN_INSTALL_DIR");
char cmdLine[MAX_PATH];
if(dokanPath) sprintf(cmdLine, "\"%s/dokanctl.exe\" /u %s", dokanPath, path);
else sprintf(cmdLine, "dokanctl.exe /u %s", path);
STARTUPINFO info = {sizeof(info)};
PROCESS_INFORMATION procInfo;
CreateProcess(NULL, cmdLine, NULL, NULL, false, CREATE_NO_WINDOW, NULL, NULL, &info, &procInfo);
WaitForSingleObject(procInfo.hProcess, INFINITE);
DWORD exitCode = -1;
GetExitCodeProcess(procInfo.hProcess, &exitCode);
CloseHandle(procInfo.hProcess);
CloseHandle(procInfo.hThread);
return exitCode;
// dokanctl.exe requires admin permissions for some reason, so if node is not run as admin,
// it'll fail to create the process for unmounting. The path will be unmounted once
// the process is killed, however, so there's that!
}
#else
#include <unistd.h>
#include <sys/wait.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void thread_create (abstr_thread_t* thread, thread_fn fn, void* data) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(thread, &attr, fn, data);
}
void thread_join (abstr_thread_t thread) {
pthread_join(thread, NULL);
}
int fusermount (char *path) {
char *argv[] = {(char *) "fusermount", (char *) "-q", (char *) "-u", path, NULL};
return execute_command_and_wait(argv);
}
#endif