This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new fd2db8856b Fix proper termination of gunicorn when it hangs (#30188)
fd2db8856b is described below

commit fd2db8856b36556b77d277a63c38c666816429c3
Author: Jarek Potiuk <[email protected]>
AuthorDate: Mon Mar 20 10:59:48 2023 +0100

    Fix proper termination of gunicorn when it hangs (#30188)
    
    During refactoring of the internal API background test, it was
    found that the SIGKILL termination of gunicorn in case it was not
    responding to SIGTERM (introduced in #11734) has never been working
    properly. The code assumed that gunicorn_master_process was
    of the subprocess.Popen type and used .poll() method to check if the
    process is still running and it would issue sigkill in such case.
    
    However the Process we have there is a psutil.Process and it has
    no poll() method - instead we can use is_running() method, which
    has the added advantage that is_running() is also checking if the
    pid has not been reused by another process after terminating the
    original gunicorn.
    
    The result of it was this error:
    
    ```
    AttributeError: 'Process' object has no attribute 'poll'
    ```
---
 airflow/cli/commands/internal_api_command.py | 4 ++--
 airflow/cli/commands/webserver_command.py    | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/airflow/cli/commands/internal_api_command.py 
b/airflow/cli/commands/internal_api_command.py
index 19ab7ab985..c78ac09e28 100644
--- a/airflow/cli/commands/internal_api_command.py
+++ b/airflow/cli/commands/internal_api_command.py
@@ -134,14 +134,14 @@ def internal_api(args):
         # then have a copy of the app
         run_args += ["--preload"]
 
-        gunicorn_master_proc = None
+        gunicorn_master_proc: psutil.Process | None = None
 
         def kill_proc(signum, _):
             log.info("Received signal: %s. Closing gunicorn.", signum)
             gunicorn_master_proc.terminate()
             with suppress(TimeoutError):
                 gunicorn_master_proc.wait(timeout=30)
-            if gunicorn_master_proc.poll() is not None:
+            if gunicorn_master_proc.is_running():
                 gunicorn_master_proc.kill()
             sys.exit(0)
 
diff --git a/airflow/cli/commands/webserver_command.py 
b/airflow/cli/commands/webserver_command.py
index a14f6a38e7..685cc42889 100644
--- a/airflow/cli/commands/webserver_command.py
+++ b/airflow/cli/commands/webserver_command.py
@@ -425,14 +425,14 @@ def webserver(args):
         # then have a copy of the app
         run_args += ["--preload"]
 
-        gunicorn_master_proc = None
+        gunicorn_master_proc: psutil.Process | None = None
 
         def kill_proc(signum, _):
             log.info("Received signal: %s. Closing gunicorn.", signum)
             gunicorn_master_proc.terminate()
             with suppress(TimeoutError):
                 gunicorn_master_proc.wait(timeout=30)
-            if gunicorn_master_proc.poll() is not None:
+            if gunicorn_master_proc.is_running():
                 gunicorn_master_proc.kill()
             sys.exit(0)
 

Reply via email to