Skip to content

Commit

Permalink
ccmlib/common.py: update pid_listening_on to return multiple pids
Browse files Browse the repository at this point in the history
in some situations, like when running cassandra 4.1, we can endup
with some of the commands in this function return multiple pids
and not just one process

to handle that we just return all of the pids back.
in the enad it's just used for debug printing about who's holding
the ports.
  • Loading branch information
fruch committed Nov 14, 2024
1 parent 20ca37c commit 8e15c88
Showing 1 changed file with 17 additions and 16 deletions.
33 changes: 17 additions & 16 deletions ccmlib/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,15 +730,15 @@ def validate_install_dir(install_dir):
raise ArgumentError(f'{install_dir} does not appear to be a cassandra or dse installation directory')


def pid_listening_on(addr: str, port: int):
def pids_listening_on(addr: str, port: int) -> List[int]:
'''get pid of the process listening on the given port'''
pid = -1
pids = []
if lsof := shutil.which('lsof'):
result = subprocess.run([lsof, '-t', '-i', f'tcp@{addr}:{port}'],
stdout=subprocess.PIPE,
check=True)
if result.stdout:
pid = int(result.stdout)
pids = [int(p) for p in result.stdout.split()]
elif ss := shutil.which('ss'):
result = subprocess.run([ss,
'--no-header',
Expand All @@ -748,12 +748,12 @@ def pid_listening_on(addr: str, port: int):
f'src = inet:{addr}:{port}'],
stdout=subprocess.PIPE,
check=True)
matched = re.search(r'pid=(\d+)', result.stdout)
matched = re.search(r'pid=(\d+)', str(result.stdout))
if matched is not None:
pid = int(matched.group(1))
pids = [int(matched.group(1))]
else:
logger.info("neither lsof nor ss was found")
return pid
return pids


def check_socket_available(itf):
Expand All @@ -771,18 +771,19 @@ def check_socket_available(itf):
except socket.error as msg:
s.close()
addr, port = itf
pid = pid_listening_on(addr, port)
if pid == -1:
pids = pids_listening_on(addr, port)
if not pids:
logger.error('Address %s:%d used unknown process')
else:
p = psutil.Process(pid)
secs_ago = p.create_time()
fmt = '%H:%M:%S' if secs_ago < 60 * 60 * 24 else '%Y-%m-%d %H:%M:%S'
since = datetime.fromtimestamp(secs_ago).strftime(fmt)
logger.error('Address %s:%d used by: "%s" '
'(pid: %d, since: %s, parent: "%s")',
addr, port, ' '.join(p.cmdline()),
p.pid, since, ' '.join(p.parent().cmdline()))
for pid in pids:
p = psutil.Process(pid)
secs_ago = p.create_time()
fmt = '%H:%M:%S' if secs_ago < 60 * 60 * 24 else '%Y-%m-%d %H:%M:%S'
since = datetime.fromtimestamp(secs_ago).strftime(fmt)
logger.error('Address %s:%d used by: "%s" '
'(pid: %d, since: %s, parent: "%s")',
addr, port, ' '.join(p.cmdline()),
p.pid, since, ' '.join(p.parent().cmdline()))
raise UnavailableSocketError(f'Inet address {addr}:{port} is not available: {msg}')


Expand Down

0 comments on commit 8e15c88

Please sign in to comment.