Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/drunc/process_manager/interface/cli_argument.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ def wrapper(f0):
multiple=True,
help="Select the process of a particular UUIDs",
)(f3)
return generate_process_query(f4, at_least_one, all_processes_by_default)
f5 = click.option(
"--crash",
is_flag=True,
default=False,
help="Simulate a crash: send SIGKILL without any cleanup, leaving the process manager in an unexpected-death state.",
)(f4)
return generate_process_query(f5, at_least_one, all_processes_by_default)

return wrapper
89 changes: 32 additions & 57 deletions src/drunc/process_manager/process_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,9 @@
BootRequest,
LogLines,
LogRequest,
ProcessDescription,
ProcessInstance,
ProcessInstanceList,
ProcessQuery,
ProcessRestriction,
ProcessUUID,
)
from druncschema.process_manager_pb2_grpc import ProcessManagerServicer
from druncschema.request_response_pb2 import (
Expand Down Expand Up @@ -448,6 +445,10 @@ def ps(

return response

@abc.abstractmethod
def _flush_impl(self, query: ProcessQuery) -> ProcessInstanceList:
raise NotImplementedError

# ORDER MATTERS!
@broadcasted # outer most wrapper 1st step
@authentified_and_authorised(
Expand All @@ -456,64 +457,38 @@ def ps(
def flush(
self, request: ProcessQuery, context: ServicerContext
) -> ProcessInstanceList:
"""Remove dead processes from tracking so they no longer appear in ps.

Dead processes that were killed externally (e.g. via kill -9) will remain
visible in ps until flushed. This command clears them from internal state
so they cannot be restarted and will not appear in subsequent ps output.

Args:
request: ProcessQuery specifying which processes to flush.
context: gRPC servicer context (unused directly).

Returns:
ProcessInstanceList containing the processes that were flushed.
"""
self.log.debug(f"{self.name} running flush")

ret = []
for uuid in self._get_process_uid(request):
# Some unknown process was found, assume it is dead and move on
if uuid not in self.boot_request:
pu = ProcessUUID(uuid=uuid)
pi = ProcessInstance(
process_description=ProcessDescription(),
process_restriction=ProcessRestriction(),
status_code=ProcessInstance.StatusCode.DEAD,
return_code=None,
uuid=pu,
)
ret += [pi]
continue

pd = ProcessDescription()
pd.CopyFrom(self.boot_request[uuid].process_description)
pr = ProcessRestriction()
pr.CopyFrom(self.boot_request[uuid].process_restriction)
pu = ProcessUUID(uuid=uuid)

return_code = None
try:
if not self.process_store[
uuid
].is_alive(): # OMG!! remove this implementation code
return_code = self.process_store[uuid].exit_code
except Exception:
pass

# If a process is already dead, remove it from the process store
if not self.process_store[uuid].is_alive():
pi = ProcessInstance(
process_description=pd,
process_restriction=pr,
status_code=(
ProcessInstance.StatusCode.RUNNING
if self.process_store[uuid].is_alive()
else ProcessInstance.StatusCode.DEAD
),
return_code=return_code,
uuid=pu,
)
# If we know that this process has died intentionally, remove it from
# tracking
self.remove_process_from_expected_dead_processes(uuid)
try:
response = self._flush_impl(request)
except NotImplementedError:
raise DruncNotImplementedException(
message="Implementation missing",
domain="ProcessManager.flush",
)
except Exception as e:
context_msg = f"Unhandled exception in ProcessManager.flush: {e}"
self.log.exception(context_msg)

del self.process_store[uuid]
ret += [pi]
raise DruncCommandException(
message=context_msg,
domain="ProcessManager.flush",
)

return ProcessInstanceList(
name=self.name,
token=None,
values=ret,
flag=ResponseFlag.EXECUTED_SUCCESSFULLY,
)
return response

# ORDER MATTERS!
@broadcasted # outer most wrapper 1st step
Expand Down
Loading
Loading