|
|
|
|
|
|
|
|
|
import argparse |
|
import atexit |
|
import codecs |
|
import locale |
|
import os |
|
import sys |
|
|
|
|
|
|
|
|
|
|
|
def main(args): |
|
|
|
|
|
|
|
if args.port is None: |
|
sys.stderr = stderr = open(os.devnull, "w") |
|
atexit.register(stderr.close) |
|
|
|
from debugpy import adapter |
|
from debugpy.common import json, log, sockets |
|
from debugpy.adapter import clients, servers, sessions |
|
|
|
if args.for_server is not None: |
|
if os.name == "posix": |
|
|
|
|
|
|
|
|
|
|
|
if os.getsid(os.getpid()) != os.getpid(): |
|
os.setsid() |
|
if os.fork() != 0: |
|
sys.exit(0) |
|
|
|
for stdio in sys.stdin, sys.stdout, sys.stderr: |
|
if stdio is not None: |
|
stdio.close() |
|
|
|
if args.log_stderr: |
|
log.stderr.levels |= set(log.LEVELS) |
|
if args.log_dir is not None: |
|
log.log_dir = args.log_dir |
|
|
|
log.to_file(prefix="debugpy.adapter") |
|
log.describe_environment("debugpy.adapter startup environment:") |
|
|
|
servers.access_token = args.server_access_token |
|
if args.for_server is None: |
|
adapter.access_token = codecs.encode(os.urandom(32), "hex").decode("ascii") |
|
|
|
endpoints = {} |
|
try: |
|
client_host, client_port = clients.serve(args.host, args.port) |
|
except Exception as exc: |
|
if args.for_server is None: |
|
raise |
|
endpoints = {"error": "Can't listen for client connections: " + str(exc)} |
|
else: |
|
endpoints["client"] = {"host": client_host, "port": client_port} |
|
|
|
if args.for_server is not None: |
|
try: |
|
server_host, server_port = servers.serve() |
|
except Exception as exc: |
|
endpoints = {"error": "Can't listen for server connections: " + str(exc)} |
|
else: |
|
endpoints["server"] = {"host": server_host, "port": server_port} |
|
|
|
log.info( |
|
"Sending endpoints info to debug server at localhost:{0}:\n{1}", |
|
args.for_server, |
|
json.repr(endpoints), |
|
) |
|
|
|
try: |
|
sock = sockets.create_client() |
|
try: |
|
sock.settimeout(None) |
|
sock.connect(("127.0.0.1", args.for_server)) |
|
sock_io = sock.makefile("wb", 0) |
|
try: |
|
sock_io.write(json.dumps(endpoints).encode("utf-8")) |
|
finally: |
|
sock_io.close() |
|
finally: |
|
sockets.close_socket(sock) |
|
except Exception: |
|
log.reraise_exception("Error sending endpoints info to debug server:") |
|
|
|
if "error" in endpoints: |
|
log.error("Couldn't set up endpoints; exiting.") |
|
sys.exit(1) |
|
|
|
listener_file = os.getenv("DEBUGPY_ADAPTER_ENDPOINTS") |
|
if listener_file is not None: |
|
log.info( |
|
"Writing endpoints info to {0!r}:\n{1}", listener_file, json.repr(endpoints) |
|
) |
|
|
|
def delete_listener_file(): |
|
log.info("Listener ports closed; deleting {0!r}", listener_file) |
|
try: |
|
os.remove(listener_file) |
|
except Exception: |
|
log.swallow_exception( |
|
"Failed to delete {0!r}", listener_file, level="warning" |
|
) |
|
|
|
try: |
|
with open(listener_file, "w") as f: |
|
atexit.register(delete_listener_file) |
|
print(json.dumps(endpoints), file=f) |
|
except Exception: |
|
log.reraise_exception("Error writing endpoints info to file:") |
|
|
|
if args.port is None: |
|
clients.Client("stdio") |
|
|
|
|
|
|
|
|
|
atexit.register(servers.stop_serving) |
|
atexit.register(clients.stop_serving) |
|
|
|
servers.wait_until_disconnected() |
|
log.info("All debug servers disconnected; waiting for remaining sessions...") |
|
|
|
sessions.wait_until_ended() |
|
log.info("All debug sessions have ended; exiting.") |
|
|
|
|
|
def _parse_argv(argv): |
|
parser = argparse.ArgumentParser() |
|
|
|
parser.add_argument( |
|
"--for-server", type=int, metavar="PORT", help=argparse.SUPPRESS |
|
) |
|
|
|
parser.add_argument( |
|
"--port", |
|
type=int, |
|
default=None, |
|
metavar="PORT", |
|
help="start the adapter in debugServer mode on the specified port", |
|
) |
|
|
|
parser.add_argument( |
|
"--host", |
|
type=str, |
|
default="127.0.0.1", |
|
metavar="HOST", |
|
help="start the adapter in debugServer mode on the specified host", |
|
) |
|
|
|
parser.add_argument( |
|
"--access-token", type=str, help="access token expected from the server" |
|
) |
|
|
|
parser.add_argument( |
|
"--server-access-token", type=str, help="access token expected by the server" |
|
) |
|
|
|
parser.add_argument( |
|
"--log-dir", |
|
type=str, |
|
metavar="DIR", |
|
help="enable logging and use DIR to save adapter logs", |
|
) |
|
|
|
parser.add_argument( |
|
"--log-stderr", action="store_true", help="enable logging to stderr" |
|
) |
|
|
|
args = parser.parse_args(argv[1:]) |
|
|
|
if args.port is None: |
|
if args.log_stderr: |
|
parser.error("--log-stderr requires --port") |
|
if args.for_server is not None: |
|
parser.error("--for-server requires --port") |
|
|
|
return args |
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if "debugpy" not in sys.modules: |
|
|
|
sys.path[0] = sys.path[0] + "/../../" |
|
__import__("debugpy") |
|
del sys.path[0] |
|
|
|
|
|
try: |
|
locale.setlocale(locale.LC_ALL, "") |
|
except Exception: |
|
|
|
|
|
|
|
pass |
|
|
|
main(_parse_argv(sys.argv)) |
|
|