import argparse import subprocess import logging import pprint SO_SOCKET = 1 SO_KEEPALIVE = 9 def get_commands_enable_keepalive(sockfd: int): return ( "set $rsp -= sizeof(int)", "set {int}$rsp = 1", f"call (int)setsockopt({sockfd}, {SO_SOCKET}, {SO_KEEPALIVE}, $rsp, sizeof(int))", "set $rsp += sizeof(int)", ) def main(args): numeric_level = getattr(logging, args["loglevel"].upper(), None) if not isinstance(numeric_level, int): raise ValueError(f"Invalid log level: {args['loglevel']}") logging.basicConfig(level=numeric_level) cmd = ["gdb", "--pid", str(args["pid"]), "--batch-silent"] gdb_cmds = list() gdb_cmds.extend(get_commands_enable_keepalive(args["sockfd"])) logging.debug("gdb commands: %s", pprint.pformat(gdb_cmds)) cmd.extend(map(lambda gdb_cmd: f"--eval-command={gdb_cmd}", gdb_cmds)) logging.debug("Executing: %s", pprint.pformat(cmd)) subprocess.run(cmd) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--pid", type=int, required=True, help="PID of the running process to alter") parser.add_argument("--sockfd", type=int, required=True, help="Socket file-descriptor number to alter") parser.add_argument("--loglevel", default="info", help="Change log level") main(vars(parser.parse_args()))