Linux/macOS: use flock() to implement exclusive launch.
Previous implementation wasn’t correct, use a better one now. In the case of a non-clean exit we will leave a stale .pid file in FG_HOME, but we clear stale files on the next launch.
This commit is contained in:
parent
a22d7943a4
commit
f903cdfa50
2 changed files with 54 additions and 27 deletions
|
@ -473,35 +473,56 @@ bool fgInitHome()
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// write our PID, and check writeability
|
// write our PID, and check writeability
|
||||||
SGPath pidPath(dataPath, "fgfs.pid");
|
SGPath pidPath(dataPath, "fgfs_lock.pid");
|
||||||
if (pidPath.exists()) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT, "flightgear instance already running, switching to FG_HOME read-only.");
|
|
||||||
// set a marker property so terrasync/navcache don't try to write
|
|
||||||
// from secondary instances
|
|
||||||
fgSetBool("/sim/fghome-readonly", true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[16];
|
|
||||||
std::string ps = pidPath.utf8Str();
|
std::string ps = pidPath.utf8Str();
|
||||||
|
|
||||||
// do open+unlink trick to the file is deleted on exit, even if we
|
if (pidPath.exists()) {
|
||||||
// crash or exit(-1)
|
int fd = ::open(ps.c_str(), O_RDONLY, 0644);
|
||||||
ssize_t len = snprintf(buf, 16, "%d", getpid());
|
if (fd < 0) {
|
||||||
int fd = ::open(ps.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644);
|
SG_LOG(SG_GENERAL, SG_ALERT, "failed to open local file:" << pidPath
|
||||||
if (fd >= 0) {
|
<< "\n\tdue to:" << simgear::strutils::error_string(errno));
|
||||||
result = ::write(fd, buf, len) == len;
|
return false;
|
||||||
if( ::unlink(ps.c_str()) != 0 ) // delete file when app quits
|
}
|
||||||
result = false;
|
|
||||||
}
|
int err = ::flock(fd, LOCK_EX | LOCK_NB);
|
||||||
|
if (err < 0) {
|
||||||
|
if ( errno == EWOULDBLOCK) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "flightgear instance already running, switching to FG_HOME read-only.");
|
||||||
|
// set a marker property so terrasync/navcache don't try to write
|
||||||
|
// from secondary instances
|
||||||
|
fgSetBool("/sim/fghome-readonly", true);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "failed to lock file:" << pidPath
|
||||||
|
<< "\n\tdue to:" << simgear::strutils::error_string(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we locked it!
|
||||||
|
result = true;
|
||||||
|
} else {
|
||||||
|
char buf[16];
|
||||||
|
std::string ps = pidPath.utf8Str();
|
||||||
|
|
||||||
if (!result) {
|
ssize_t len = snprintf(buf, 16, "%d\n", getpid());
|
||||||
flightgear::fatalMessageBoxWithoutExit(
|
int fd = ::open(ps.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
"File permissions problem",
|
if (fd < 0) {
|
||||||
"Can't write to user-data storage folder, check file permissions "
|
SG_LOG(SG_GENERAL, SG_ALERT, "failed to open local file:" << pidPath
|
||||||
"and FG_HOME.",
|
<< "\n\tdue to:" << simgear::strutils::error_string(errno));
|
||||||
"User-data at '" + dataPath.utf8Str() + "'.");
|
return false;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
write(fd, buf, len);
|
||||||
|
|
||||||
|
int err = flock(fd, LOCK_EX);
|
||||||
|
if (err != 0) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "failed to lock file:" << pidPath
|
||||||
|
<< "\n\tdue to:" << simgear::strutils::error_string(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fgSetBool("/sim/fghome-readonly", false);
|
fgSetBool("/sim/fghome-readonly", false);
|
||||||
|
@ -514,6 +535,11 @@ void fgShutdownHome()
|
||||||
if (static_fgHomeWriteMutex) {
|
if (static_fgHomeWriteMutex) {
|
||||||
CloseHandle(static_fgHomeWriteMutex);
|
CloseHandle(static_fgHomeWriteMutex);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (fgGetBool("/sim/fghome-readonly") == false) {
|
||||||
|
SGPath pidPath = globals->get_fg_home() / "fgfs_lock.pid";
|
||||||
|
pidPath.remove();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -706,7 +706,8 @@ int fgMainInit( int argc, char **argv )
|
||||||
int result = fgOSMainLoop();
|
int result = fgOSMainLoop();
|
||||||
frame_signal.clear();
|
frame_signal.clear();
|
||||||
fgOSCloseWindow();
|
fgOSCloseWindow();
|
||||||
|
fgShutdownHome();
|
||||||
|
|
||||||
simgear::Emesary::GlobalTransmitter::instance()->NotifyAll(mln_stopped);
|
simgear::Emesary::GlobalTransmitter::instance()->NotifyAll(mln_stopped);
|
||||||
|
|
||||||
simgear::clearEffectCache();
|
simgear::clearEffectCache();
|
||||||
|
|
Loading…
Add table
Reference in a new issue