| 417 | # For containerised processes, 'port_map' should be provided to map from the container's |
| 418 | # ports to ports on the host. Methods from this class always return the host port. |
| 419 | class Process(object): |
| 420 | def __init__(self, cmd, container_id=None, port_map=None): |
| 421 | assert cmd is not None and len(cmd) >= 1,\ |
| 422 | 'Process object must be created with valid command line argument list' |
| 423 | assert container_id is None or port_map is not None,\ |
| 424 | "Must provide port_map for containerised process" |
| 425 | self.cmd = cmd |
| 426 | self.container_id = container_id |
| 427 | self.port_map = port_map |
| 428 | |
| 429 | def __class_name(self): |
| 430 | return self.__class__.__name__ |
| 431 | |
| 432 | def __str__(self): |
| 433 | return "<%s PID: %s (%s)>" % (self.__class_name(), self.__get_pid(), |
| 434 | ' '.join(self.cmd)) |
| 435 | |
| 436 | def __repr__(self): |
| 437 | return str(self) |
| 438 | |
| 439 | def get_pid(self): |
| 440 | """Gets the PID of the process. Returns None if the PID cannot be determined""" |
| 441 | pid = self.__get_pid() |
| 442 | if pid: |
| 443 | LOG.info("Found PID %s for %s" % (pid, " ".join(self.cmd))) |
| 444 | else: |
| 445 | LOG.info("No PID found for process cmdline: %s. Process is dead?" % |
| 446 | " ".join(self.cmd)) |
| 447 | return pid |
| 448 | |
| 449 | def get_pids(self): |
| 450 | """Gets the PIDs of the process. In some circumstances, a process can run multiple |
| 451 | times, e.g. when it forks in the Breakpad crash handler. Returns an empty list if no |
| 452 | PIDs can be determined.""" |
| 453 | pids = [proc['pid'] for proc in self.__get_procs()] |
| 454 | if pids: |
| 455 | LOG.info("Found PIDs %s for %s" % (", ".join(map(str, pids)), " ".join(self.cmd))) |
| 456 | else: |
| 457 | LOG.info("No PID found for process cmdline: %s. Process is dead?" % |
| 458 | " ".join(self.cmd)) |
| 459 | return pids |
| 460 | |
| 461 | def __procs_str(self, procs): |
| 462 | return "\n".join([str(proc) for proc in procs]) |
| 463 | |
| 464 | def __get_pid(self): |
| 465 | procs = self.__get_procs() |
| 466 | # Return early for containerized environments |
| 467 | if len(procs) == 1: |
| 468 | return procs[0]['pid'] |
| 469 | |
| 470 | result = None |
| 471 | # In some circumstances - notably ubsan tests - child processes can be slow to exit. |
| 472 | # Only return the original process, i.e. one who's parent has a different cmd. |
| 473 | pids = [proc['pid'] for proc in procs] |
| 474 | for process in procs: |
| 475 | if process['ppid'] not in pids: |
| 476 | assert result is None,\ |
no outgoing calls