|
@@ -35,6 +35,17 @@
|
|
#include <stdio.h>
|
|
#include <stdio.h>
|
|
#include <sys/un.h>
|
|
#include <sys/un.h>
|
|
#endif
|
|
#endif
|
|
|
|
+#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
+#include <sys/param.h>
|
|
|
|
+#include <fcntl.h>
|
|
|
|
+#include <sys/sysctl.h>
|
|
|
|
+#include <sys/user.h>
|
|
|
|
+#include <libprocstat.h>
|
|
|
|
+
|
|
|
|
+#include <condition_variable>
|
|
|
|
+#include <mutex>
|
|
|
|
+#include <thread>
|
|
|
|
+#endif
|
|
|
|
|
|
using namespace std;
|
|
using namespace std;
|
|
|
|
|
|
@@ -90,6 +101,75 @@ void RunningInstanceCheck(bool &already_running)
|
|
fclose(fp);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
+#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
|
|
+struct RunOnce {
|
|
|
|
+ std::thread thr;
|
|
|
|
+ static const char *thr_name;
|
|
|
|
+ std::condition_variable cv;
|
|
|
|
+ std::condition_variable wait_cv;
|
|
|
|
+ std::mutex mtx;
|
|
|
|
+ bool exiting = false;
|
|
|
|
+ bool name_changed = false;
|
|
|
|
+
|
|
|
|
+ void thr_proc()
|
|
|
|
+ {
|
|
|
|
+ std::unique_lock<std::mutex> lk(mtx);
|
|
|
|
+ pthread_setname_np(pthread_self(), thr_name);
|
|
|
|
+ name_changed = true;
|
|
|
|
+ wait_cv.notify_all();
|
|
|
|
+ cv.wait(lk, [this]() { return exiting; });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ~RunOnce()
|
|
|
|
+ {
|
|
|
|
+ if (thr.joinable()) {
|
|
|
|
+ std::unique_lock<std::mutex> lk(mtx);
|
|
|
|
+ exiting = true;
|
|
|
|
+ cv.notify_one();
|
|
|
|
+ lk.unlock();
|
|
|
|
+ thr.join();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+} RO;
|
|
|
|
+const char *RunOnce::thr_name = "OBS runonce";
|
|
|
|
+
|
|
|
|
+void PIDFileCheck(bool &already_running)
|
|
|
|
+{
|
|
|
|
+ std::string tmpfile_name =
|
|
|
|
+ "/tmp/obs-studio.lock." + to_string(geteuid());
|
|
|
|
+ int fd = open(tmpfile_name.c_str(), O_RDWR | O_CREAT | O_EXLOCK, 0600);
|
|
|
|
+ if (fd == -1) {
|
|
|
|
+ already_running = true;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ already_running = false;
|
|
|
|
+
|
|
|
|
+ procstat *ps = procstat_open_sysctl();
|
|
|
|
+ unsigned int count;
|
|
|
|
+ auto procs = procstat_getprocs(ps, KERN_PROC_UID | KERN_PROC_INC_THREAD,
|
|
|
|
+ geteuid(), &count);
|
|
|
|
+ for (unsigned int i = 0; i < count; i++) {
|
|
|
|
+ if (!strncmp(procs[i].ki_tdname, RunOnce::thr_name,
|
|
|
|
+ sizeof(procs[i].ki_tdname))) {
|
|
|
|
+ already_running = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ procstat_freeprocs(ps, procs);
|
|
|
|
+ procstat_close(ps);
|
|
|
|
+
|
|
|
|
+ RO.thr = std::thread(std::mem_fn(&RunOnce::thr_proc), &RO);
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ std::unique_lock<std::mutex> lk(RO.mtx);
|
|
|
|
+ RO.wait_cv.wait(lk, []() { return RO.name_changed; });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ unlink(tmpfile_name.c_str());
|
|
|
|
+ close(fd);
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
|
|
static inline bool check_path(const char *data, const char *path,
|
|
static inline bool check_path(const char *data, const char *path,
|
|
string &output)
|
|
string &output)
|