fix issues when checking EdenFS status on windows

Summary:
- Catch the Windows-specific exceptions types thrown when attempting to open
  the socket if EdenFS is not running, and convert this to an EdenNotRunning
  exception.
- Update EdenFS to write its pid to a separate file, in addition to the normal
  lock file, and have `edenfsctl` read this file instead of the lock file on
  Windows.  Other processes cannot read the lock file while EdenFS is running
  and holding the lock, so it is nice to have the pid written in an alternate
  location.

Reviewed By: pkaush

Differential Revision: D20854615

fbshipit-source-id: 1c8e8f402eb17dd012d03e11fbb662f493d9362d
This commit is contained in:
Adam Simpkins 2020-04-15 15:44:15 -07:00 committed by Facebook GitHub Bot
parent b1a35b8252
commit 104ae880db
3 changed files with 29 additions and 5 deletions

View File

@ -30,6 +30,7 @@ if sys.platform != "win32":
# These paths are relative to the user's client directory.
LOCK_FILE = "lock"
PID_FILE = "pid"
class EdenStartError(Exception):
@ -102,7 +103,16 @@ def poll_until(
def get_pid_using_lockfile(config_dir: Path) -> int:
"""Read the pid from the Eden lockfile, throwing an exception upon failure.
"""
lockfile = config_dir / LOCK_FILE
if sys.platform == "win32":
# On Windows read the separate pid file. We will not be able to read the
# lock file if EdenFS is running and holding the lock.
lockfile = config_dir / PID_FILE
else:
# On other platforms we still prefer reading the pid from the lock file,
# just to support older instances of EdenFS that only wrote the pid to the lock
# file.
lockfile = config_dir / LOCK_FILE
with lockfile.open("r") as f:
lockfile_contents = f.read()
return int(lockfile_contents.rstrip())

View File

@ -18,10 +18,13 @@ from thrift.transport.TTransport import TTransportException
if sys.platform == "win32":
from eden.thrift.windows_thrift import WinTSocket # @manual
from eden.thrift.windows_thrift import WinTSocket, WindowsSocketException # @manual
else:
from thrift.transport.TSocket import TSocket
class WindowsSocketException(Exception):
pass
SOCKET_PATH = "socket"
@ -91,15 +94,18 @@ class EdenClient(EdenService.Client):
def open(self):
# type: () -> None
transport = self._transport
assert transport is not None
try:
assert self._transport is not None
# pyre-fixme[16]: `Optional` has no attribute `open`.
self._transport.open()
transport.open()
except TTransportException as ex:
self.close()
if ex.type == TTransportException.NOT_OPEN:
raise EdenNotRunningError(self._socket_path)
raise
except WindowsSocketException:
self.close()
raise EdenNotRunningError(self._socket_path)
def close(self):
# type: () -> None

View File

@ -14,6 +14,7 @@ using folly::StringPiece;
namespace {
constexpr StringPiece kLockFileName{"lock"};
constexpr StringPiece kPidFileName{"pid"};
constexpr StringPiece kTakeoverSocketName{"takeover"};
constexpr StringPiece kThriftSocketName{"socket"};
} // namespace
@ -42,6 +43,13 @@ void EdenStateDir::takeoverLock(folly::File lockFile) {
int rc = fstat(lockFile.fd(), &lockFileStat_);
folly::checkUnixError(rc, "error getting lock file attributes");
lockFile_ = std::move(lockFile);
// On Windows, also write the pid to a separate file.
// Other processes cannot read the lock file while we are holding the lock,
// so we store it in a separate file too.
auto pidFilePath = path_ + PathComponentPiece(kPidFileName);
folly::File pidFile(pidFilePath.c_str(), O_WRONLY | O_CREAT, 0644);
writePidToLockFile(pidFile);
}
folly::File EdenStateDir::extractLock() {