### What problem does this PR solve? This patch add signal for ctrl + c that can exit the code friendly cause code base use thread daemon can not exit friendly for being started. how to reproduce 1. docker-compose -f docker/docker-compose-base.yml up 2. other window `bash docker/launch_backend_service.sh` 3. stop 1 first 4. try to stop 2 then two thread can not exit which must use `kill pid` This patch fix it and should fix most the related issues in the `issues` ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) --------- Signed-off-by: yihong0618 <zouzou0208@gmail.com>tags/v0.17.0
| import time | import time | ||||
| import traceback | import traceback | ||||
| from concurrent.futures import ThreadPoolExecutor | from concurrent.futures import ThreadPoolExecutor | ||||
| import threading | |||||
| from werkzeug.serving import run_simple | from werkzeug.serving import run_simple | ||||
| from api import settings | from api import settings | ||||
| from api.utils import show_configs | from api.utils import show_configs | ||||
| from rag.settings import print_rag_settings | from rag.settings import print_rag_settings | ||||
| stop_event = threading.Event() | |||||
| def update_progress(): | def update_progress(): | ||||
| while True: | |||||
| time.sleep(6) | |||||
| while not stop_event.is_set(): | |||||
| try: | try: | ||||
| DocumentService.update_progress() | DocumentService.update_progress() | ||||
| stop_event.wait(6) | |||||
| except Exception: | except Exception: | ||||
| logging.exception("update_progress exception") | logging.exception("update_progress exception") | ||||
| def signal_handler(sig, frame): | |||||
| logging.info("Received interrupt signal, shutting down...") | |||||
| stop_event.set() | |||||
| time.sleep(1) | |||||
| sys.exit(0) | |||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||
| logging.info(r""" | logging.info(r""" | ||||
| RuntimeConfig.init_env() | RuntimeConfig.init_env() | ||||
| RuntimeConfig.init_config(JOB_SERVER_HOST=settings.HOST_IP, HTTP_PORT=settings.HOST_PORT) | RuntimeConfig.init_config(JOB_SERVER_HOST=settings.HOST_IP, HTTP_PORT=settings.HOST_PORT) | ||||
| signal.signal(signal.SIGINT, signal_handler) | |||||
| signal.signal(signal.SIGTERM, signal_handler) | |||||
| thread = ThreadPoolExecutor(max_workers=1) | thread = ThreadPoolExecutor(max_workers=1) | ||||
| thread.submit(update_progress) | thread.submit(update_progress) | ||||
| ) | ) | ||||
| except Exception: | except Exception: | ||||
| traceback.print_exc() | traceback.print_exc() | ||||
| stop_event.set() | |||||
| time.sleep(1) | |||||
| os.kill(os.getpid(), signal.SIGKILL) | os.kill(os.getpid(), signal.SIGKILL) |
| if TRACE_MALLOC_ENABLED: | if TRACE_MALLOC_ENABLED: | ||||
| start_tracemalloc_and_snapshot(None, None) | start_tracemalloc_and_snapshot(None, None) | ||||
| # Create an event to signal the background thread to exit | |||||
| stop_event = threading.Event() | |||||
| background_thread = threading.Thread(target=report_status) | background_thread = threading.Thread(target=report_status) | ||||
| background_thread.daemon = True | background_thread.daemon = True | ||||
| background_thread.start() | background_thread.start() | ||||
| # Handle SIGINT (Ctrl+C) | |||||
| def signal_handler(sig, frame): | |||||
| logging.info("Received Ctrl+C, shutting down gracefully...") | |||||
| stop_event.set() | |||||
| # Give the background thread time to clean up | |||||
| if background_thread.is_alive(): | |||||
| background_thread.join(timeout=5) | |||||
| logging.info("Exiting...") | |||||
| sys.exit(0) | |||||
| signal.signal(signal.SIGINT, signal_handler) | |||||
| while True: | |||||
| handle_task() | |||||
| try: | |||||
| while not stop_event.is_set(): | |||||
| handle_task() | |||||
| except KeyboardInterrupt: | |||||
| logging.info("Interrupted by keyboard, shutting down...") | |||||
| stop_event.set() | |||||
| if background_thread.is_alive(): | |||||
| background_thread.join(timeout=5) | |||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||
| main() | main() |