Skip to content

Commit 0a06442

Browse files
committed
Postfix for #7197: Segfault in linux CS after successful detach from database: add forgotten new file
1 parent 91bfc41 commit 0a06442

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

src/jrd/ThreadCollect.h

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* PROGRAM: JRD threading support
3+
* MODULE: ThreadCollect.h
4+
* DESCRIPTION: Threads' group completion handling
5+
*
6+
* The contents of this file are subject to the Initial
7+
* Developer's Public License Version 1.0 (the "License");
8+
* you may not use this file except in compliance with the
9+
* License. You may obtain a copy of the License at
10+
* http://www.firebirdsql.org/en/initial-developer-s-public-license-version-1-0/
11+
*
12+
* Software distributed under the License is distributed AS IS,
13+
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing rights
15+
* and limitations under the License.
16+
*
17+
* The Original Code was created by Alexander Peshkov
18+
* for the Firebird Open Source RDBMS project.
19+
*
20+
* Copyright (c) 2018, 2022 Alexander Peshkov <[email protected]>
21+
* and all contributors signed below.
22+
*
23+
* All Rights Reserved.
24+
* Contributor(s): ______________________________________.
25+
*
26+
*
27+
*/
28+
29+
#ifndef JRD_THREADCOLLECT_H
30+
#define JRD_THREADCOLLECT_H
31+
32+
#include "../common/ThreadStart.h"
33+
#include "../common/classes/alloc.h"
34+
#include "../common/classes/array.h"
35+
#include "../common/classes/locks.h"
36+
37+
38+
namespace Jrd {
39+
40+
class ThreadCollect
41+
{
42+
public:
43+
ThreadCollect(MemoryPool& p)
44+
: threads(p)
45+
{ }
46+
47+
void join()
48+
{
49+
if (!threads.hasData())
50+
return;
51+
52+
waitFor(threads);
53+
}
54+
55+
void ending(Thread::Handle& h)
56+
{
57+
// put thread into completion wait queue when it finished running
58+
Firebird::MutexLockGuard g(threadsMutex, FB_FUNCTION);
59+
60+
for (unsigned n = 0; n < threads.getCount(); ++n)
61+
{
62+
if (threads[n].hndl == h)
63+
{
64+
threads[n].ending = true;
65+
return;
66+
}
67+
}
68+
69+
Thrd t = {h, true};
70+
threads.add(t);
71+
}
72+
73+
void running(Thread::Handle& h)
74+
{
75+
// put thread into completion wait queue when it starts running
76+
Firebird::MutexLockGuard g(threadsMutex, FB_FUNCTION);
77+
78+
Thrd t = {h, false};
79+
threads.add(t);
80+
}
81+
82+
void houseKeeping()
83+
{
84+
if (!threads.hasData())
85+
return;
86+
87+
// join finished threads
88+
AllThreads t;
89+
{ // mutex scope
90+
Firebird::MutexLockGuard g(threadsMutex, FB_FUNCTION);
91+
92+
for (unsigned n = 0; n < threads.getCount(); )
93+
{
94+
if (threads[n].ending)
95+
{
96+
t.add(threads[n]);
97+
threads.remove(n);
98+
}
99+
else
100+
++n;
101+
}
102+
}
103+
104+
waitFor(t);
105+
}
106+
107+
private:
108+
struct Thrd
109+
{
110+
Thread::Handle hndl;
111+
bool ending;
112+
};
113+
typedef Firebird::HalfStaticArray<Thrd, 4> AllThreads;
114+
115+
void waitFor(AllThreads& thr)
116+
{
117+
Firebird::MutexLockGuard g(threadsMutex, FB_FUNCTION);
118+
while (thr.hasData())
119+
{
120+
FB_SIZE_T n = thr.getCount() - 1;
121+
Thrd& t = thr[n];
122+
{
123+
Firebird::MutexUnlockGuard u(threadsMutex, FB_FUNCTION);
124+
Thread::waitForCompletion(t.hndl);
125+
fb_assert(t.ending);
126+
}
127+
thr.remove(n);
128+
}
129+
}
130+
131+
AllThreads threads;
132+
Firebird::Mutex threadsMutex;
133+
};
134+
135+
} // namespace Jrd
136+
137+
138+
#endif // JRD_THREADCOLLECT_H

0 commit comments

Comments
 (0)