Skip to content

Commit 2fe9183

Browse files
authored
Merge pull request #5 from wanteddev/signal-thread-join
Add `signal`, `atexit` module for non-daemon GPT thread join
2 parents 8289a4c + 3b2b403 commit 2fe9183

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

app.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import os
22
import json
3+
import signal
4+
import atexit
5+
import threading
36
import contextlib
47
from json import JSONDecodeError
58
from urllib.request import urlopen, Request, HTTPError
6-
from threading import Thread
79

810
import sentry_sdk
911
from 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
517519
app = 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
531573
if __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

Comments
 (0)