11# ------------------------------------------------------------------------------
2- # Copyright (c) 2020, 2023 , Oracle and/or its affiliates.
2+ # Copyright (c) 2020, 2024 , Oracle and/or its affiliates.
33#
44# This software is dual-licensed to you under the Universal Permissive License
55# (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
@@ -442,8 +442,7 @@ cdef class ThinPoolImpl(BaseThinPoolImpl):
442442 super ().__init__(dsn, params)
443443 self ._condition = threading.Condition()
444444 self ._bg_task_condition = threading.Condition()
445- self ._bg_task = threading.Thread(target = self ._bg_task_func,
446- daemon = True )
445+ self ._bg_task = threading.Thread(target = self ._bg_task_func)
447446 self ._bg_task.start()
448447
449448 def _bg_task_func (self ):
@@ -459,6 +458,9 @@ cdef class ThinPoolImpl(BaseThinPoolImpl):
459458 list conn_impls_to_drop
460459 bint wait
461460
461+ # add to the list of pools that require closing
462+ pools_to_close.add(self )
463+
462464 # create connections and close connections as needed
463465 while True :
464466 conn_impls_to_drop = []
@@ -499,6 +501,9 @@ cdef class ThinPoolImpl(BaseThinPoolImpl):
499501 with self ._bg_task_condition:
500502 self ._bg_task_condition.wait()
501503
504+ # remove from the list of pools that require closing
505+ pools_to_close.remove(self )
506+
502507 cdef ThinConnImpl _create_conn_impl(self , ConnectParamsImpl params = None ):
503508 """
504509 Create a single connection using the pool's information. This
@@ -638,11 +643,14 @@ cdef class ThinPoolImpl(BaseThinPoolImpl):
638643
639644 def close (self , bint force ):
640645 """
641- Internal method for closing the pool.
646+ Internal method for closing the pool. Note that the thread to destroy
647+ pools gracefully may have already run, so if the close has already
648+ happened, nothing more needs to be done!
642649 """
643- with self ._condition:
644- self ._close_helper(force)
645- self ._bg_task.join()
650+ if self in pools_to_close:
651+ with self ._condition:
652+ self ._close_helper(force)
653+ self ._bg_task.join()
646654
647655 def drop (self , ThinConnImpl conn_impl ):
648656 """
@@ -883,3 +891,13 @@ cdef class AsyncThinPoolImpl(BaseThinPoolImpl):
883891 self ._busy_conn_impls.remove(conn_impl)
884892 self ._drop_conn_impl(conn_impl)
885893 self ._condition.notify()
894+
895+ # keep track of which pools need to be closed and ensure that they are closed
896+ # gracefully when the main thread finishes its work
897+ pools_to_close = set ()
898+ def close_pools_gracefully ():
899+ cdef ThinPoolImpl pool_impl
900+ threading.main_thread().join() # wait for main thread to finish
901+ for pool_impl in list (pools_to_close):
902+ pool_impl.close(True )
903+ threading.Thread(target = close_pools_gracefully).start()
0 commit comments