Coverage Report

Created: 2025-11-16 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/log4cplus/src/threads.cxx
Line
Count
Source
1
// Module:  Log4CPLUS
2
// File:    threads.cxx
3
// Created: 6/2001
4
// Author:  Tad E. Smith
5
//
6
//
7
// Copyright 2001-2017 Tad E. Smith
8
//
9
// Licensed under the Apache License, Version 2.0 (the "License");
10
// you may not use this file except in compliance with the License.
11
// You may obtain a copy of the License at
12
//
13
//     http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software
16
// distributed under the License is distributed on an "AS IS" BASIS,
17
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
// See the License for the specific language governing permissions and
19
// limitations under the License.
20
21
#include <log4cplus/config.hxx>
22
23
#include <exception>
24
#include <ostream>
25
#include <cerrno>
26
27
#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H
28
#include <sys/types.h>
29
#endif
30
31
#ifdef LOG4CPLUS_HAVE_SYS_SYSCALL_H
32
#include <sys/syscall.h>
33
#endif
34
35
#ifdef LOG4CPLUS_HAVE_ERRNO_H
36
#include <errno.h>
37
#endif
38
39
#ifdef LOG4CPLUS_HAVE_UNISTD_H
40
#include <unistd.h>
41
#endif
42
43
#if defined(LOG4CPLUS_USE_PTHREADS)
44
#  include <pthread.h>
45
#  include <sched.h>
46
#  include <signal.h>
47
#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
48
#  include <process.h>
49
#endif
50
#include <log4cplus/config/windowsh-inc.h>
51
#include <log4cplus/thread/syncprims-pub-impl.h>
52
#include <log4cplus/tstring.h>
53
#include <log4cplus/internal/cygwin-win32.h>
54
#include <log4cplus/streams.h>
55
56
#include <log4cplus/thread/threads.h>
57
58
#ifndef LOG4CPLUS_SINGLE_THREADED
59
60
#include <log4cplus/thread/impl/threads-impl.h>
61
#include <log4cplus/thread/impl/tls.h>
62
#include <log4cplus/ndc.h>
63
#include <log4cplus/helpers/loglog.h>
64
#include <log4cplus/helpers/stringhelper.h>
65
#include <log4cplus/helpers/timehelper.h>
66
#include <log4cplus/internal/internal.h>
67
68
#endif // LOG4CPLUS_SINGLE_THREADED
69
70
71
namespace log4cplus { namespace thread {
72
73
LOG4CPLUS_EXPORT
74
void
75
blockAllSignals()
76
0
{
77
0
#if defined (LOG4CPLUS_USE_PTHREADS)
78
    // Block all signals.
79
0
    sigset_t signal_set;
80
0
    sigfillset (&signal_set);
81
0
    pthread_sigmask (SIG_BLOCK, &signal_set, nullptr);
82
0
#endif
83
0
}
84
85
86
LOG4CPLUS_EXPORT
87
void
88
yield()
89
0
{
90
0
#if defined(LOG4CPLUS_USE_PTHREADS)
91
0
    sched_yield();
92
#elif defined(_WIN32)
93
    if (! SwitchToThread ())
94
        Sleep (0);
95
#endif
96
0
}
97
98
#if defined(LOG4CPLUS_SINGLE_THREADED)
99
static log4cplus::tstring thread_name
100
    LOG4CPLUS_INIT_PRIORITY (LOG4CPLUS_INIT_PRIORITY_BASE - 1)
101
    (LOG4CPLUS_TEXT("single"));
102
static log4cplus::tstring thread_name2
103
    LOG4CPLUS_INIT_PRIORITY (LOG4CPLUS_INIT_PRIORITY_BASE - 1)
104
    (thread_name);
105
#endif
106
107
LOG4CPLUS_EXPORT
108
log4cplus::tstring const &
109
getCurrentThreadName()
110
604k
{
111
604k
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
112
604k
    log4cplus::tstring & name = log4cplus::internal::get_thread_name_str ();
113
604k
    if (LOG4CPLUS_UNLIKELY (name.empty ()))
114
24
    {
115
24
        log4cplus::tostringstream tmp;
116
24
        tmp << impl::getCurrentThreadId ();
117
24
        name = tmp.str ();
118
24
    }
119
#else
120
    log4cplus::tstring & name = thread_name;
121
    if (LOG4CPLUS_UNLIKELY(name.empty()))
122
    {
123
        name = LOG4CPLUS_TEXT("single");
124
    }
125
#endif
126
127
604k
    return name;
128
604k
}
129
130
131
namespace
132
{
133
134
135
static
136
bool
137
get_current_thread_name_alt (log4cplus::tostream * s)
138
0
{
139
0
    log4cplus::tostream & os = *s;
140
141
0
#if defined (LOG4CPLUS_USE_PTHREADS) && defined (__linux__) \
142
0
    && defined (LOG4CPLUS_HAVE_GETTID)
143
0
    pid_t tid = syscall (SYS_gettid);
144
0
    os << tid;
145
146
#elif defined (__CYGWIN__)
147
    unsigned long tid = cygwin::get_current_win32_thread_id ();
148
    os << tid;
149
150
#else
151
    os << getCurrentThreadName ();
152
153
#endif
154
155
0
    return true;
156
0
}
157
158
159
} // namespace
160
161
162
LOG4CPLUS_EXPORT
163
log4cplus::tstring const &
164
getCurrentThreadName2()
165
0
{
166
0
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
167
0
    log4cplus::tstring & name = log4cplus::internal::get_thread_name2_str ();
168
0
    if (LOG4CPLUS_UNLIKELY (name.empty ()))
169
0
    {
170
0
        log4cplus::tostringstream tmp;
171
0
        get_current_thread_name_alt (&tmp);
172
0
        name = tmp.str ();
173
0
    }
174
175
#else
176
    log4cplus::tstring & name = thread_name2;
177
    if (LOG4CPLUS_UNLIKELY(name.empty()))
178
    {
179
        name = getCurrentThreadName();
180
    }
181
182
#endif
183
184
0
    return name;
185
0
}
186
187
LOG4CPLUS_EXPORT void setCurrentThreadName(const log4cplus::tstring & name)
188
0
{
189
0
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
190
0
    log4cplus::internal::get_thread_name_str() = name;
191
#else
192
    thread_name = name;
193
#endif
194
0
}
195
196
LOG4CPLUS_EXPORT void setCurrentThreadName2(const log4cplus::tstring & name)
197
0
{
198
0
#if ! defined (LOG4CPLUS_SINGLE_THREADED)
199
0
    log4cplus::internal::get_thread_name2_str() = name;
200
#else
201
    thread_name2 = name;
202
#endif
203
0
}
204
205
206
//
207
//
208
//
209
210
struct SignalsBlocker::SignalsBlockerImpl
211
{
212
#if defined (LOG4CPLUS_USE_PTHREADS)
213
    sigset_t signal_set;
214
#endif
215
};
216
217
218
SignalsBlocker::SignalsBlocker ()
219
36
    : impl (new SignalsBlocker::SignalsBlockerImpl)
220
36
{
221
36
#if defined (LOG4CPLUS_USE_PTHREADS)
222
36
    sigset_t block_all_set;
223
36
    sigfillset (&block_all_set);
224
36
    (void) pthread_sigmask (SIG_BLOCK, &block_all_set, &impl->signal_set);
225
36
#endif
226
36
}
227
228
229
SignalsBlocker::~SignalsBlocker()
230
36
{
231
36
#if defined (LOG4CPLUS_USE_PTHREADS)
232
36
    (void) pthread_sigmask (SIG_SETMASK, &impl->signal_set, nullptr);
233
36
#endif
234
36
}
235
236
237
#ifndef LOG4CPLUS_SINGLE_THREADED
238
239
//
240
//
241
//
242
243
AbstractThread::AbstractThread ()
244
0
    : flags (0)
245
0
{ }
246
247
248
bool
249
AbstractThread::isRunning() const
250
0
{
251
0
    return (flags & fRUNNING) != 0;
252
0
}
253
254
255
void
256
AbstractThread::start()
257
0
{
258
0
    try
259
0
    {
260
0
        flags |= fRUNNING;
261
0
        thread.reset (
262
0
            new std::thread ([this] (AbstractThreadPtr const & thread_ptr) {
263
0
                    (void) thread_ptr;
264
0
                    blockAllSignals ();
265
0
                    helpers::LogLog & loglog = helpers::getLogLog();
266
0
                    try
267
0
                    {
268
0
                        this->run ();
269
0
                    }
270
0
                    catch (std::exception const & e)
271
0
                    {
272
0
                        tstring err (LOG4CPLUS_TEXT ("threadStartFunc()")
273
0
                            LOG4CPLUS_TEXT ("- run() terminated with an exception: "));
274
0
                        err += LOG4CPLUS_C_STR_TO_TSTRING(e.what());
275
0
                        loglog.warn(err);
276
0
                    }
277
0
                    catch(...)
278
0
                    {
279
0
                        loglog.warn(LOG4CPLUS_TEXT("threadStartFunc()")
280
0
                            LOG4CPLUS_TEXT ("- run() terminated with an exception."));
281
0
                    }
282
0
                    this->flags &= ~fRUNNING;
283
0
                    threadCleanup ();
284
0
                }, AbstractThreadPtr (this)));
285
0
    }
286
0
    catch (...)
287
0
    {
288
0
        flags &= ~fRUNNING;
289
0
        throw;
290
0
    }
291
0
}
292
293
294
void
295
AbstractThread::join () const
296
0
{
297
0
    if (! thread
298
0
        || (flags & fJOINED) == fJOINED)
299
0
        throw std::logic_error ("this thread is not running");
300
301
0
    thread->join ();
302
0
    flags |= +fJOINED;
303
0
}
304
305
306
AbstractThread::~AbstractThread()
307
0
{
308
0
    if ((flags & fJOINED) == 0)
309
0
        thread->detach ();
310
0
}
311
312
#endif // LOG4CPLUS_SINGLE_THREADED
313
314
315
} } // namespace log4cplus { namespace thread {