Fix the missing env variable issue (#5467)
Fixes #5448, #5453, #5457 - Relaxed env var requirements in the images, no mandatory ones - RQ workers now use a custom python class for remote debugging - Factored out common remote debugging implementationmain
parent
7b13216e2d
commit
f6d2a8fe46
@ -0,0 +1,56 @@
|
||||
# Copyright (C) 2018-2022 Intel Corporation
|
||||
# Copyright (C) 2022 CVAT.ai Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from rq import Worker
|
||||
|
||||
import cvat.utils.remote_debugger as debug
|
||||
|
||||
|
||||
DefaultWorker = Worker
|
||||
|
||||
|
||||
class BaseDeathPenalty:
|
||||
def __init__(self, timeout, exception, **kwargs):
|
||||
pass
|
||||
|
||||
def __enter__(self):
|
||||
pass
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
pass
|
||||
|
||||
|
||||
class SimpleWorker(Worker):
|
||||
"""
|
||||
Allows to work with at most 1 worker thread. Useful for debugging.
|
||||
"""
|
||||
|
||||
death_penalty_class = BaseDeathPenalty
|
||||
|
||||
def main_work_horse(self, *args, **kwargs):
|
||||
raise NotImplementedError("Test worker does not implement this method")
|
||||
|
||||
def execute_job(self, *args, **kwargs):
|
||||
"""Execute job in same thread/process, do not fork()"""
|
||||
return self.perform_job(*args, **kwargs)
|
||||
|
||||
|
||||
if debug.is_debugging_enabled():
|
||||
class RemoteDebugWorker(SimpleWorker):
|
||||
"""
|
||||
Support for VS code debugger
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.__debugger = debug.RemoteDebugger()
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def execute_job(self, *args, **kwargs):
|
||||
"""Execute job in same thread/process, do not fork()"""
|
||||
self.__debugger.attach_current_thread()
|
||||
|
||||
return super().execute_job(*args, **kwargs)
|
||||
|
||||
DefaultWorker = RemoteDebugWorker
|
||||
@ -1,28 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018-2022 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from rq import Worker
|
||||
|
||||
|
||||
class BaseDeathPenalty:
|
||||
def __init__(self, timeout, exception, **kwargs):
|
||||
pass
|
||||
|
||||
def __enter__(self):
|
||||
pass
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
pass
|
||||
|
||||
|
||||
class SimpleWorker(Worker):
|
||||
death_penalty_class = BaseDeathPenalty
|
||||
|
||||
def main_work_horse(self, *args, **kwargs):
|
||||
raise NotImplementedError("Test worker does not implement this method")
|
||||
|
||||
def execute_job(self, *args, **kwargs):
|
||||
"""Execute job in same thread/process, do not fork()"""
|
||||
return self.perform_job(*args, **kwargs)
|
||||
@ -0,0 +1,59 @@
|
||||
# Copyright (C) 2022 CVAT.ai Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def is_debugging_enabled() -> bool:
|
||||
return os.environ.get('CVAT_DEBUG_ENABLED') == 'yes'
|
||||
|
||||
if is_debugging_enabled():
|
||||
import debugpy
|
||||
|
||||
class RemoteDebugger:
|
||||
"""
|
||||
Support for VS code debugger.
|
||||
|
||||
Supports both single- and multi-thread scenarios.
|
||||
|
||||
Read docs: https://github.com/microsoft/debugpy
|
||||
Read more: https://modwsgi.readthedocs.io/en/develop/user-guides/debugging-techniques.html
|
||||
"""
|
||||
|
||||
ENV_VAR_PORT = 'CVAT_DEBUG_PORT'
|
||||
ENV_VAR_WAIT = 'CVAT_DEBUG_WAIT'
|
||||
__debugger_initialized = False
|
||||
|
||||
@classmethod
|
||||
def _singleton_init(cls):
|
||||
if cls.__debugger_initialized:
|
||||
return
|
||||
|
||||
try:
|
||||
port = int(os.environ[cls.ENV_VAR_PORT])
|
||||
|
||||
# The only intended use is in Docker.
|
||||
# Using 127.0.0.1 will not allow host connections
|
||||
addr = ('0.0.0.0', port) # nosec - B104:hardcoded_bind_all_interfaces
|
||||
|
||||
# Debugpy is a singleton
|
||||
# We put it in the main thread of the process and then report new threads
|
||||
debugpy.listen(addr)
|
||||
|
||||
# In most cases it makes no sense to debug subprocesses
|
||||
# Feel free to enable if needed.
|
||||
debugpy.configure({"subProcess": False})
|
||||
|
||||
if os.environ.get(cls.ENV_VAR_WAIT) == 'yes':
|
||||
debugpy.wait_for_client()
|
||||
except Exception as ex:
|
||||
raise Exception("failed to set debugger") from ex
|
||||
|
||||
cls.__debugger_initialized = True
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._singleton_init()
|
||||
|
||||
def attach_current_thread(self) -> None:
|
||||
debugpy.debug_this_thread()
|
||||
Loading…
Reference in New Issue