|
111 | 111 | #include "../yvalve/why_proto.h"
|
112 | 112 | #include "../jrd/flags.h"
|
113 | 113 | #include "../jrd/Mapping.h"
|
| 114 | +#include "../jrd/ThreadCollect.h" |
114 | 115 |
|
115 | 116 | #include "../jrd/Database.h"
|
116 | 117 |
|
|
124 | 125 | #include "../common/classes/fb_tls.h"
|
125 | 126 | #include "../common/classes/ClumpletWriter.h"
|
126 | 127 | #include "../common/classes/RefMutex.h"
|
| 128 | +#include "../common/classes/semaphore.h" |
127 | 129 | #include "../common/utils_proto.h"
|
128 | 130 | #include "../jrd/DebugInterface.h"
|
129 | 131 | #include "../jrd/CryptoManager.h"
|
@@ -449,6 +451,16 @@ namespace
|
449 | 451 | {
|
450 | 452 | using Jrd::Attachment;
|
451 | 453 |
|
| 454 | + // Required to sync attachment shutdown threads with provider shutdown |
| 455 | + GlobalPtr<ThreadCollect> shutThreadCollect; |
| 456 | + |
| 457 | + struct AttShutParams |
| 458 | + { |
| 459 | + Semaphore thdStartedSem; |
| 460 | + Thread::Handle thrHandle; |
| 461 | + AttachmentsRefHolder* attachments; |
| 462 | + }; |
| 463 | + |
452 | 464 | // Flag engineShutdown guarantees that no new attachment is created after setting it
|
453 | 465 | // and helps avoid more than 1 shutdown threads running simultaneously.
|
454 | 466 | bool engineShutdown = false;
|
@@ -4130,59 +4142,65 @@ void JProvider::shutdown(CheckStatusWrapper* status, unsigned int timeout, const
|
4130 | 4142 | **************************************/
|
4131 | 4143 | try
|
4132 | 4144 | {
|
4133 |
| - MutexLockGuard guard(shutdownMutex, FB_FUNCTION); |
4134 |
| - |
4135 |
| - if (engineShutdown) |
4136 |
| - { |
4137 |
| - return; |
4138 |
| - } |
4139 | 4145 | { // scope
|
4140 |
| - MutexLockGuard guard(newAttachmentMutex, FB_FUNCTION); |
4141 |
| - engineShutdown = true; |
4142 |
| - } |
| 4146 | + MutexLockGuard guard(shutdownMutex, FB_FUNCTION); |
4143 | 4147 |
|
4144 |
| - ThreadContextHolder tdbb; |
| 4148 | + if (engineShutdown) |
| 4149 | + { |
| 4150 | + return; |
| 4151 | + } |
4145 | 4152 |
|
4146 |
| - ULONG attach_count, database_count, svc_count; |
4147 |
| - JRD_enum_attachments(NULL, attach_count, database_count, svc_count); |
| 4153 | + { // scope |
| 4154 | + MutexLockGuard guard(newAttachmentMutex, FB_FUNCTION); |
| 4155 | + engineShutdown = true; |
| 4156 | + } |
4148 | 4157 |
|
4149 |
| - if (attach_count > 0 || svc_count > 0) |
4150 |
| - { |
4151 |
| - gds__log("Shutting down the server with %d active connection(s) to %d database(s), " |
4152 |
| - "%d active service(s)", |
4153 |
| - attach_count, database_count, svc_count); |
4154 |
| - } |
| 4158 | + ThreadContextHolder tdbb; |
4155 | 4159 |
|
4156 |
| - if (reason == fb_shutrsn_exit_called) |
4157 |
| - { |
4158 |
| - // Starting threads may fail when task is going to close. |
4159 |
| - // This happens at least with some microsoft C runtimes. |
4160 |
| - // If people wish to have timeout, they should better call fb_shutdown() themselves. |
4161 |
| - // Therefore: |
4162 |
| - timeout = 0; |
4163 |
| - } |
| 4160 | + ULONG attach_count, database_count, svc_count; |
| 4161 | + JRD_enum_attachments(NULL, attach_count, database_count, svc_count); |
4164 | 4162 |
|
4165 |
| - if (timeout) |
4166 |
| - { |
4167 |
| - Semaphore shutdown_semaphore; |
| 4163 | + if (attach_count > 0 || svc_count > 0) |
| 4164 | + { |
| 4165 | + gds__log("Shutting down the server with %d active connection(s) to %d database(s), " |
| 4166 | + "%d active service(s)", |
| 4167 | + attach_count, database_count, svc_count); |
| 4168 | + } |
4168 | 4169 |
|
4169 |
| - Thread::Handle h; |
4170 |
| - Thread::start(shutdown_thread, &shutdown_semaphore, THREAD_medium, &h); |
| 4170 | + if (reason == fb_shutrsn_exit_called) |
| 4171 | + { |
| 4172 | + // Starting threads may fail when task is going to close. |
| 4173 | + // This happens at least with some microsoft C runtimes. |
| 4174 | + // If people wish to have timeout, they should better call fb_shutdown() themselves. |
| 4175 | + // Therefore: |
| 4176 | + timeout = 0; |
| 4177 | + } |
4171 | 4178 |
|
4172 |
| - if (!shutdown_semaphore.tryEnter(0, timeout)) |
4173 |
| - waitForShutdown(shutdown_semaphore); |
| 4179 | + if (timeout) |
| 4180 | + { |
| 4181 | + Semaphore shutdown_semaphore; |
4174 | 4182 |
|
4175 |
| - Thread::waitForCompletion(h); |
4176 |
| - } |
4177 |
| - else |
4178 |
| - { |
4179 |
| - shutdown_thread(NULL); |
| 4183 | + Thread::Handle h; |
| 4184 | + Thread::start(shutdown_thread, &shutdown_semaphore, THREAD_medium, &h); |
| 4185 | + |
| 4186 | + if (!shutdown_semaphore.tryEnter(0, timeout)) |
| 4187 | + waitForShutdown(shutdown_semaphore); |
| 4188 | + |
| 4189 | + Thread::waitForCompletion(h); |
| 4190 | + } |
| 4191 | + else |
| 4192 | + { |
| 4193 | + shutdown_thread(NULL); |
| 4194 | + } |
| 4195 | + |
| 4196 | + // Do not put it into separate shutdown thread - during shutdown of TraceManager |
| 4197 | + // PluginManager wants to lock a mutex, which is sometimes already locked in current thread |
| 4198 | + TraceManager::shutdown(); |
| 4199 | + shutdownMappingIpc(); |
4180 | 4200 | }
|
4181 | 4201 |
|
4182 |
| - // Do not put it into separate shutdown thread - during shutdown of TraceManager |
4183 |
| - // PluginManager wants to lock a mutex, which is sometimes already locked in current thread |
4184 |
| - TraceManager::shutdown(); |
4185 |
| - shutdownMappingIpc(); |
| 4202 | + // Wait for completion of all shutdown threads |
| 4203 | + shutThreadCollect->join(); |
4186 | 4204 | }
|
4187 | 4205 | catch (const Exception& ex)
|
4188 | 4206 | {
|
@@ -7478,22 +7496,26 @@ namespace
|
7478 | 7496 | ThreadModuleRef thdRef(attachmentShutdownThread, &engineShutdown);
|
7479 | 7497 | #endif
|
7480 | 7498 |
|
| 7499 | + AttShutParams* params = static_cast<AttShutParams*>(arg); |
| 7500 | + AttachmentsRefHolder* attachments = params->attachments; |
| 7501 | + Thread::Handle th = params->thrHandle; |
| 7502 | + fb_assert(th); |
| 7503 | + |
7481 | 7504 | try
|
7482 | 7505 | {
|
7483 |
| - MutexLockGuard guard(shutdownMutex, FB_FUNCTION); |
7484 |
| - if (engineShutdown) |
7485 |
| - { |
7486 |
| - // Shutdown was done, all attachments are gone |
7487 |
| - return 0; |
7488 |
| - } |
| 7506 | + shutThreadCollect->running(th); |
| 7507 | + params->thdStartedSem.release(); |
7489 | 7508 |
|
7490 |
| - shutdownAttachments(static_cast<AttachmentsRefHolder*>(arg), false); |
| 7509 | + MutexLockGuard guard(shutdownMutex, FB_FUNCTION); |
| 7510 | + if (!engineShutdown) |
| 7511 | + shutdownAttachments(attachments, false); |
7491 | 7512 | }
|
7492 | 7513 | catch (const Exception& ex)
|
7493 | 7514 | {
|
7494 | 7515 | iscLogException("attachmentShutdownThread", ex);
|
7495 | 7516 | }
|
7496 | 7517 |
|
| 7518 | + shutThreadCollect->ending(th); |
7497 | 7519 | return 0;
|
7498 | 7520 | }
|
7499 | 7521 | } // anonymous namespace
|
@@ -8183,7 +8205,12 @@ void JRD_shutdown_attachment(Attachment* attachment)
|
8183 | 8205 | if (!(attachment->att_flags & ATT_shutdown))
|
8184 | 8206 | attachment->signalShutdown();
|
8185 | 8207 |
|
8186 |
| - Thread::start(attachmentShutdownThread, queue.release(), THREAD_high); |
| 8208 | + AttShutParams params; |
| 8209 | + params.attachments = queue; |
| 8210 | + Thread::start(attachmentShutdownThread, ¶ms, THREAD_high, ¶ms.thrHandle); |
| 8211 | + queue.release(); |
| 8212 | + shutThreadCollect->houseKeeping(); |
| 8213 | + params.thdStartedSem.enter(); |
8187 | 8214 | }
|
8188 | 8215 | catch (const Exception&)
|
8189 | 8216 | {} // no-op
|
@@ -8239,7 +8266,12 @@ void JRD_shutdown_attachments(Database* dbb)
|
8239 | 8266 | attachment->signalShutdown();
|
8240 | 8267 | }
|
8241 | 8268 |
|
8242 |
| - Thread::start(attachmentShutdownThread, queue.release(), THREAD_high); |
| 8269 | + AttShutParams params; |
| 8270 | + params.attachments = queue; |
| 8271 | + Thread::start(attachmentShutdownThread, ¶ms, THREAD_high, ¶ms.thrHandle); |
| 8272 | + queue.release(); |
| 8273 | + shutThreadCollect->houseKeeping(); |
| 8274 | + params.thdStartedSem.enter(); |
8243 | 8275 | }
|
8244 | 8276 | }
|
8245 | 8277 | catch (const Exception&)
|
|
0 commit comments