1
1
# ------------------------------------------------------------------------------
2
- # Copyright (c) 2020, 2023 , Oracle and/or its affiliates.
2
+ # Copyright (c) 2020, 2024 , Oracle and/or its affiliates.
3
3
#
4
4
# This software is dual-licensed to you under the Universal Permissive License
5
5
# (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
@@ -442,8 +442,7 @@ cdef class ThinPoolImpl(BaseThinPoolImpl):
442
442
super ().__init__(dsn, params)
443
443
self ._condition = threading.Condition()
444
444
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)
447
446
self ._bg_task.start()
448
447
449
448
def _bg_task_func (self ):
@@ -459,6 +458,9 @@ cdef class ThinPoolImpl(BaseThinPoolImpl):
459
458
list conn_impls_to_drop
460
459
bint wait
461
460
461
+ # add to the list of pools that require closing
462
+ pools_to_close.add(self )
463
+
462
464
# create connections and close connections as needed
463
465
while True :
464
466
conn_impls_to_drop = []
@@ -499,6 +501,9 @@ cdef class ThinPoolImpl(BaseThinPoolImpl):
499
501
with self ._bg_task_condition:
500
502
self ._bg_task_condition.wait()
501
503
504
+ # remove from the list of pools that require closing
505
+ pools_to_close.remove(self )
506
+
502
507
cdef ThinConnImpl _create_conn_impl(self , ConnectParamsImpl params = None ):
503
508
"""
504
509
Create a single connection using the pool's information. This
@@ -638,11 +643,14 @@ cdef class ThinPoolImpl(BaseThinPoolImpl):
638
643
639
644
def close (self , bint force ):
640
645
"""
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!
642
649
"""
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()
646
654
647
655
def drop (self , ThinConnImpl conn_impl ):
648
656
"""
@@ -883,3 +891,13 @@ cdef class AsyncThinPoolImpl(BaseThinPoolImpl):
883
891
self ._busy_conn_impls.remove(conn_impl)
884
892
self ._drop_conn_impl(conn_impl)
885
893
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