-
-
Notifications
You must be signed in to change notification settings - Fork 652
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Port the pantsd nailgun server to rust (#9722)
### Problem The setup and teardown of each request made to the nailgun server in `pantsd` had become quite complicated over time... and consequently, slower than it needed to be. ### Solution Port `pantsd`'s nailgun server to rust using the `nails` crate. Additionally, remove the `Exiter` class, which had accumulated excess responsibilities that can instead be handled by returning `ExitCode` values. Finally, fix a few broken windows including: double logging to pantsd, double help output, closed file errors on pantsd shutdown, and redundant setup codepaths. ### Result There is less code to maintain, and runs of `./pants --enable-pantsd help` take `~1.7s`, of which `~400ms` are spent in the server. Fixes #9448, fixes #8243, fixes #8206, fixes #8127, fixes #7653, fixes #7613, fixes #7597.
- Loading branch information
Stu Hood
authored
May 13, 2020
1 parent
bfb59ac
commit 9506fbf
Showing
51 changed files
with
1,177 additions
and
2,003 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,8 @@ | ||
# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). | ||
# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md). | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
import logging | ||
import sys | ||
import traceback | ||
from typing import Callable, Union | ||
|
||
from pants.util.strutil import ensure_binary | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
# Centralize integer return codes for the pants process. We just use a single bit for now. | ||
# TODO: make these into an enum! | ||
PANTS_SUCCEEDED_EXIT_CODE = 0 | ||
PANTS_FAILED_EXIT_CODE = 1 | ||
|
||
ExitCode = int | ||
|
||
|
||
class Exiter: | ||
"""A class that provides standard runtime exit behavior. | ||
`pants.base.exception_sink.ExceptionSink` handles exceptions and fatal signals, delegating to an | ||
Exiter instance which can be set process-globally with ExceptionSink.reset_exiter(). Call | ||
.exit() or .exit_and_fail() on an Exiter instance when you wish to exit the runtime. | ||
""" | ||
|
||
def __init__(self, exiter: Callable[[Union[ExitCode, str, object]], None] = sys.exit): | ||
""" | ||
:param exiter: A function to be called to conduct the final exit of the runtime. (Optional) | ||
""" | ||
# Since we have some exit paths that run via the sys.excepthook, | ||
# symbols we use can become garbage collected before we use them; ie: | ||
# we can find `sys` and `traceback` are `None`. As a result we capture | ||
# all symbols we need here to ensure we function in excepthook context. | ||
# See: http://stackoverflow.com/questions/2572172/referencing-other-modules-in-atexit | ||
self._exit = exiter | ||
|
||
def __call__(self, *args, **kwargs): | ||
"""Map class calls to self.exit() to support sys.exit() fungibility.""" | ||
return self.exit(*args, **kwargs) | ||
|
||
def exit(self, result=PANTS_SUCCEEDED_EXIT_CODE, msg=None, out=None): | ||
"""Exits the runtime. | ||
:param result: The exit status. Typically either PANTS_SUCCEEDED_EXIT_CODE or | ||
PANTS_FAILED_EXIT_CODE, but can be a string as well. (Optional) | ||
:param msg: A string message to print to stderr or another custom file desciptor before exiting. | ||
(Optional) | ||
:param out: The file descriptor to emit `msg` to. (Optional) | ||
""" | ||
if msg: | ||
out = out or sys.stderr | ||
if hasattr(out, "buffer"): | ||
out = out.buffer | ||
|
||
msg = ensure_binary(msg) | ||
try: | ||
out.write(msg) | ||
out.write(b"\n") | ||
# TODO: Determine whether this call is a no-op because the stream gets flushed on exit, or | ||
# if we could lose what we just printed, e.g. if we get interrupted by a signal while | ||
# exiting and the stream is buffered like stdout. | ||
out.flush() | ||
except Exception as e: | ||
# If the file is already closed, or any other error occurs, just log it and continue to | ||
# exit. | ||
if msg: | ||
logger.warning( | ||
"Encountered error when trying to log this message: {}, \n " | ||
"exception: {} \n out: {}".format(msg, e, out) | ||
) | ||
# In pantsd, this won't go anywhere, because there's really nowhere for us to log if we | ||
# can't log :( | ||
# Not in pantsd, this will end up in sys.stderr. | ||
traceback.print_stack() | ||
logger.exception(e) | ||
self._exit(result) | ||
|
||
def exit_and_fail(self, msg=None, out=None): | ||
"""Exits the runtime with a nonzero exit code, indicating failure. | ||
:param msg: A string message to print to stderr or another custom file desciptor before exiting. | ||
(Optional) | ||
:param out: The file descriptor to emit `msg` to. (Optional) | ||
""" | ||
self.exit(result=PANTS_FAILED_EXIT_CODE, msg=msg, out=out) | ||
# Centralize integer return codes for the pants process. | ||
PANTS_SUCCEEDED_EXIT_CODE: ExitCode = 0 | ||
PANTS_FAILED_EXIT_CODE: ExitCode = 1 |
Oops, something went wrong.