11import os
22import json
3+ import signal
4+ import atexit
5+ import threading
36import contextlib
47from json import JSONDecodeError
58from urllib .request import urlopen , Request , HTTPError
6- from threading import Thread
79
810import sentry_sdk
911from slack_bolt import App
@@ -515,6 +517,7 @@ def laas_jira_thread(event, client, say, collection):
515517
516518# Initializes your app with your bot token and socket mode handler
517519app = App (token = os .environ ['SLACK_BOT_TOKEN' ])
520+ is_exiting = False
518521
519522
520523@app .event ("reaction_added" )
@@ -524,11 +527,53 @@ def reaction(event, client, say):
524527 """
525528 match event ['reaction' ]:
526529 case PICollection .trigger_emoji :
527- t = Thread (target = laas_jira_thread , args = (event , client , say , PICollection ))
530+ t = threading . Thread (target = laas_jira_thread , args = (event , client , say , PICollection ), daemon = False )
528531 t .start ()
529532
530533
534+ def os_term_handler (signum , frame ):
535+ """
536+ 이 함수는 운영 체제 시그널에 대한 핸들러입니다. 애플리케이션이 종료 시그널(SIGTERM)을 받으면 at_exit_handler() 함수를 호출합니다.
537+
538+ AWS 콘솔에서 ECS 중지 버튼을 클릭한 경우는 SIGTERM 을 호출합니다.
539+ SIGTERM 이후 30초 동안 프로세스가 종료되지 않으면 SIGKILL 을 호출합니다.
540+ try - finally 로직을 타지 않습니다.
541+ """
542+ signame = signal .Signals (signum ).name
543+ print (f'SIGNAL received: { signame } ({ signum } )' )
544+ print ('Frame:' , frame )
545+
546+ at_exit_handler ()
547+
548+
549+ @atexit .register
550+ def at_exit_handler ():
551+ """
552+ 애플리케이션이 종료되려 할 때 호출됩니다.
553+ 참고: 이 모듈을 통해 등록된 함수는 다음과 같은 경우 호출되지 않습니다.
554+ - 프로그램이 파이썬이 처리하지 않는 시그널에 의해 종료될 때.
555+ - 파이썬의 치명적인 내부 에러가 감지되었을 때.
556+ - os._exit() 가 호출될 때.
557+
558+ 모든 실행 중인 스레드를 순회합니다.
559+ 스레드가 메인 스레드가 아니고 daemon이 아닌 스레드라면, 스레드가 실행을 마칠 때까지 기다립니다(스레드에 join합니다).
560+ """
561+ print ('AtExit handler' )
562+ # sys.exit()을 호출할 경우 atexit을 중복 호출 할 수 있으므로 global 변수로 관리합니다.
563+ global is_exiting
564+ if is_exiting :
565+ return
566+ is_exiting = True
567+ # 일반적으로 파일의 정상적인 닫힘, 메모리의 정리 등이 필요한 상황에서는 sys.exit 예외를 발생시켜 Python의 정상적인 종료 프로세스를 따르도록 하며, atexit에 등록된 함수들도 실행됩니다.
568+ import sys
569+ sys .exit (0 )
570+
571+
572+ # Start your app
531573if __name__ == "__main__" :
574+ signal .signal (signal .SIGINT , os_term_handler )
575+ signal .signal (signal .SIGTERM , os_term_handler )
576+
532577 # Sentry 등 초기화 코드가 있다면 여기에 작성합니다.
533578 sentry_sdk .init (
534579 dsn = os .environ ['SENTRY_DSN' ],
0 commit comments