add initiateShutdown() thrift method with a shutdown reason

Summary:
We've seen what appears to be phantom calls to shutdown() so we'd like
to add some degree of auditing.  This diff adds a new method with some
context; this will allow us to distinguish between `eden stop`, `eden restart`
and eden server internal calls to the `shutdown` method.   It may still
be possible that something else is calling our shutdown method, but it
seems unlikely as we're only accessible to our own code via a unix domain
socket.

Reviewed By: chadaustin

Differential Revision: D8341595

fbshipit-source-id: 50d58ea0b56e5f42cd37c404048d710bde0d13a3
This commit is contained in:
Wez Furlong 2018-06-19 10:57:55 -07:00 committed by Facebook Github Bot
parent 31321c3460
commit bfad766a21
6 changed files with 56 additions and 3 deletions

View File

@ -739,7 +739,10 @@ class RestartCmd(Subcmd):
stop_aux_processes(client)
# Ask the old edenfs daemon to shutdown
self.msg("Stopping the existing edenfs daemon (pid {})...", pid)
client.shutdown()
client.initiateShutdown(
f"`eden restart` requested by pid={os.getpid()} "
f"uid={os.getuid()}"
)
stopping = True
except EdenNotRunningError:
pass
@ -832,7 +835,9 @@ class StopCmd(Subcmd):
stop_aux_processes(client)
# Ask the client to shutdown
print(f"Stopping edenfs daemon (pid {pid})...")
client.shutdown()
client.initiateShutdown(
f"`eden stop` requested by pid={os.getpid()} uid={os.getuid()}"
)
except EdenNotRunningError:
print_stderr("error: edenfs is not running")
return SHUTDOWN_EXIT_CODE_NOT_RUNNING_ERROR

View File

@ -981,5 +981,11 @@ void EdenServiceHandler::shutdown() {
auto helper = INSTRUMENT_THRIFT_CALL(INFO);
server_->stop();
}
void EdenServiceHandler::initiateShutdown(std::unique_ptr<std::string> reason) {
auto helper = INSTRUMENT_THRIFT_CALL(INFO);
XLOG(INFO) << "initiateShutdown requested, reason: " << *reason;
server_->stop();
}
} // namespace eden
} // namespace facebook

View File

@ -166,10 +166,18 @@ class EdenServiceHandler : virtual public StreamingEdenServiceSvIf,
/**
* When this Thrift handler is notified to shutdown, it notifies the
* EdenServer to shut down, as well.
* EdenServer to shut down, as well. We prefer that external
* clients use initiateShutdown() instead so that we can log some
* context.
*/
void shutdown() override;
/**
* A thrift client has requested that we shutdown and provided
* the reason why.
*/
void initiateShutdown(std::unique_ptr<std::string> reason) override;
private:
folly::Future<Hash> getSHA1ForPath(
folly::StringPiece mountPoint,

View File

@ -12,6 +12,7 @@ from typing import Any, cast
from facebook.eden import EdenService
from thrift.protocol.THeaderProtocol import THeaderProtocol
from thrift.Thrift import TApplicationException
from thrift.transport.THeaderTransport import THeaderTransport
from thrift.transport.TSocket import TSocket
from thrift.transport.TTransport import TTransportException
@ -85,6 +86,29 @@ class EdenClient(EdenService.Client):
self._transport.close()
self._transport = None
def shutdown(self):
self.initiateShutdown(
"EdenClient.shutdown() invoked with no reason by pid=%s uid=%s"
% (os.getpid(), os.getuid())
)
def initiateShutdown(self, reason):
"""Helper for stopping the server.
To swing through the transition from calling the base shutdown() method
with context to the initiateShutdown() method with a reason, we want to
try the latter method first, falling back to the old way to handle the
case where we deploy a newer client while an older server is still
running on the local system."""
try:
super().initiateShutdown(reason)
except TApplicationException as ex:
if ex.type == TApplicationException.UNKNOWN_METHOD:
# Running an older server build, fall back to the old shutdown
# method with no context
super().shutdown()
else:
raise
def create_thrift_client(eden_dir=None, socket_path=None):
"""Construct a thrift client to speak to the running eden server

View File

@ -676,4 +676,9 @@ service EdenService extends fb303.FacebookService {
* Gets the number of inodes unloaded by periodic job on an EdenMount.
*/
InternalStats getStatInfo() throws (1: EdenError ex)
/**
* Ask the server to shutdown and provide it some context for its logs
*/
void initiateShutdown(1: string reason);
}

View File

@ -57,6 +57,11 @@ class FakeEdenServiceHandler : virtual public StreamingEdenServiceSvIf {
void shutdown() override {
printf("received shutdown() thrift request\n");
}
void initiateShutdown(std::unique_ptr<std::string> reason) override {
printf(
"received initiateShutdown() thrift requested: %s\n", reason->c_str());
}
};
class SignalHandler : public folly::AsyncSignalHandler {