• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

19.57
/libs/full/runtime_components/src/console_logging.cpp
1
//  Copyright (c) 2007-2025 Hartmut Kaiser
2
//  Copyright (c)      2011 Bryce Lelbach
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#include <hpx/config.hpp>
9
#include <hpx/agas/addressing_service.hpp>
10
#include <hpx/assert.hpp>
11
#include <hpx/async_distributed/continuation.hpp>
12
#include <hpx/async_distributed/detail/post.hpp>
13
#include <hpx/components_base/agas_interface.hpp>
14
#include <hpx/modules/concurrency.hpp>
15
#include <hpx/modules/datastructures.hpp>
16
#include <hpx/modules/errors.hpp>
17
#include <hpx/modules/logging.hpp>
18
#include <hpx/modules/runtime_local.hpp>
19
#include <hpx/modules/static_reinit.hpp>
20
#include <hpx/modules/synchronization.hpp>
21
#include <hpx/modules/thread_support.hpp>
22
#include <hpx/modules/threadmanager.hpp>
23
#include <hpx/modules/type_support.hpp>
24
#include <hpx/naming_base/id_type.hpp>
25
#include <hpx/runtime_components/console_logging.hpp>
26
#include <hpx/runtime_components/server/console_logging.hpp>
27

28
#include <atomic>
29
#include <cstddef>
30
#include <mutex>
31
#include <string>
32

33
#include <hpx/config/warnings_prefix.hpp>
34

35
///////////////////////////////////////////////////////////////////////////////
36
namespace hpx { namespace components {
37

×
38
    void fallback_console_logging_locked(
39
        messages_type const& msgs, std::string fail_msg = "")
40
    {
41
        using hpx::get;
42

×
43
        if (!fail_msg.empty())
×
44
            fail_msg = "Logging failed due to: " + fail_msg + "\n";
45

×
46
        for (std::size_t i = 0; i != msgs.size(); ++i)
47
        {
48
            message_type const& msg = msgs[i];
×
49
            switch (get<0>(msg))
50
            {
51
            // NOLINTNEXTLINE(bugprone-branch-clone)
×
52
            default:
53
            case logging_destination::hpx:
×
54
                LHPX_CONSOLE_(get<1>(msg)) << fail_msg << get<2>(msg);
55
                break;
56

×
57
            case logging_destination::timing:
×
58
                LTIM_CONSOLE_(get<1>(msg)) << fail_msg << get<2>(msg);
59
                break;
60

×
61
            case logging_destination::agas:
×
62
                LAGAS_CONSOLE_(get<1>(msg)) << fail_msg << get<2>(msg);
63
                break;
64

×
65
            case logging_destination::parcel:
×
66
                LPT_CONSOLE_(get<1>(msg)) << fail_msg << get<2>(msg);
67
                break;
68

×
69
            case logging_destination::app:
×
70
                LAPP_CONSOLE_(get<1>(msg)) << fail_msg << get<2>(msg);
71
                break;
72

×
73
            case logging_destination::debuglog:
×
74
                LDEB_CONSOLE_ << fail_msg << get<2>(msg);
75
                break;
76
            }
77
        }
×
78
    }
79

×
80
    void console_logging_locked(
81
        hpx::id_type const& prefix, messages_type const& msgs)
82
    {
83
        // If we're not in an HPX thread, we cannot call apply as it may access
84
        // the AGAS components. We just throw an exception here - there's no
85
        // thread-manager, so the exception will probably be unhandled. This is
86
        // desirable in this situation, as we can't trust the logging system to
87
        // report this error.
×
88
        if (HPX_UNLIKELY(!threads::get_self_ptr()))
89
        {
90
            // write the message to a local file in any case
×
91
            fallback_console_logging_locked(msgs);
92

93
            // raise error as this should get called from outside a HPX-thread
×
94
            HPX_THROW_EXCEPTION(hpx::error::null_thread_id,
95
                "components::console_logging_locked",
96
                "console_logging_locked was not called from a HPX-thread");
97
        }
98

99
        try
100
        {
101
            hpx::post<server::console_logging_action<>>(prefix, msgs);
102
        }
×
103
        catch (hpx::exception const& e)
104
        {
105
            // if this is not the console locality (or any other error occurs)
106
            // we might be too late for any logging, write to local file
×
107
            fallback_console_logging_locked(msgs, e.what());
×
108
        }
×
109
    }
110

111
    ///////////////////////////////////////////////////////////////////////////
112
    struct HPX_EXPORT pending_logs
113
    {
114
        using prefix_mutex_type = hpx::mutex;
115
        using queue_mutex_type = util::spinlock;
116

117
        enum
118
        {
119
            max_pending = 128
120
        };
121

32✔
122
        pending_logs()
32✔
123
          : prefix_mtx_()
124
          , prefix_(hpx::invalid_id)
125
          , queue_mtx_()
126
          , activated_(false)
127
          , is_sending_(false)
128
        {
32✔
129
        }
130

131
        void add(message_type const& msg);
132

133
        void cleanup();
134

135
        void activate()
136
        {
137
            activated_.store(true);
138
        }
139

140
    private:
141
        bool ensure_prefix();
142
        void send();
143
        bool is_active();
144

145
        prefix_mutex_type prefix_mtx_;
146
        hpx::id_type prefix_;
147

148
        queue_mutex_type queue_mtx_;
149
        messages_type queue_;
150

151
        std::atomic<bool> activated_;
152
        std::atomic<bool> is_sending_;
153
    };
154

×
155
    bool pending_logs::is_active()
156
    {
×
157
        return threads::get_self_ptr() &&
×
158
            threads::threadmanager_is(hpx::state::running) && activated_.load();
159
    }
160

×
161
    void pending_logs::add(message_type const& msg)
162
    {
×
163
        if (nullptr == hpx::get_runtime_ptr())
164
        {
165
            // This branch will be taken if it's too early or too late in the
166
            // game. We do local logging only. Any queued messages which may be
167
            // still left in the queue are logged locally as well.
168

169
            // queue up the new message and log it with the rest of it
×
170
            messages_type msgs;
171
            {
×
172
                std::lock_guard<queue_mutex_type> l(queue_mtx_);
×
173
                queue_.push_back(msg);
174
                queue_.swap(msgs);
175
            }
176

×
177
            fallback_console_logging_locked(msgs);
×
178
        }
×
179
        else if (is_active())
180
        {
181
            // This branch will be taken under normal circumstances. We queue
182
            // up the message and either log it immediately (if we are on the
183
            // console locality) or defer logging until 'max_pending' messages
184
            // have been queued. Note: we can invoke send only from within a
185
            // HPX-thread.
186
            std::size_t size = 0;
187

188
            {
×
189
                std::lock_guard<queue_mutex_type> l(queue_mtx_);
×
190
                queue_.push_back(msg);
191
                size = queue_.size();
192
            }
193

194
            // Invoke actual logging immediately if we're on the console or
195
            // if the number of waiting log messages is too large.
×
196
            if (agas::is_console() || size > max_pending)
×
197
                send();
198
        }
199
        else
200
        {
201
            // This branch will be taken if the runtime is up and running, but
202
            // either the thread manager is not active or this is not invoked
203
            // on a HPX-thread.
204

205
            // Note: is_console can be called outside of a HPX-thread
×
206
            if (!agas::is_console())
207
            {
208
                // queue it for delivery to the console
×
209
                std::lock_guard<queue_mutex_type> l(queue_mtx_);
×
210
                queue_.push_back(msg);
211
            }
212
            else
213
            {
214
                // log it locally on the console
×
215
                messages_type msgs;
×
216
                msgs.push_back(msg);
×
217
                fallback_console_logging_locked(msgs);
×
218
            }
219
        }
×
220
    }
221

32✔
222
    void pending_logs::cleanup()
223
    {
64✔
224
        if (threads::threadmanager_is(hpx::state::running) &&
32✔
225
            threads::get_self_ptr())
226
        {
32✔
227
            send();
228
        }
229
        else
230
        {
×
231
            messages_type msgs;
232
            {
×
233
                std::lock_guard<queue_mutex_type> l(queue_mtx_);
×
234
                if (queue_.empty())
235
                    return;    // some other thread did the deed
236
                queue_.swap(msgs);
237
            }
238

×
239
            fallback_console_logging_locked(msgs);
×
240
        }
241
    }
242

×
243
    bool pending_logs::ensure_prefix()
244
    {
245
        // Resolve the console prefix if it's still invalid.
×
246
        if (HPX_UNLIKELY(hpx::invalid_id == prefix_))
247
        {
248
            std::unique_lock<prefix_mutex_type> l(
×
249
                prefix_mtx_, std::try_to_lock);
250

×
251
            if (l.owns_lock() && (hpx::invalid_id == prefix_))
252
            {
×
253
                naming::gid_type raw_prefix;
254
                {
255
                    unlock_guard<std::unique_lock<prefix_mutex_type>> ul(l);
×
256
                    naming::get_agas_client().get_console_locality(raw_prefix);
257
                }
258

259
                HPX_ASSERT(naming::invalid_gid != raw_prefix);
260
                if (!prefix_)
261
                {
×
262
                    prefix_ = hpx::id_type(
263
                        raw_prefix, hpx::id_type::management_type::unmanaged);
264
                }
265
                else
266
                {
267
                    HPX_ASSERT(prefix_.get_gid() == raw_prefix);
268
                }
269
            }
270

271
            // Someone else started getting the console prefix.
272
            else
273
            {
274
                return false;
275
            }
276
        }
277
        return true;
278
    }
279

32✔
280
    void pending_logs::send()
281
    {
282
        // WARNING: Never, ever call this outside of a HPX-thread.
283
        HPX_ASSERT(threads::get_self_ptr());
284

32✔
285
        bool expected = false;
32✔
286
        if (!is_sending_.compare_exchange_strong(expected, true))
32✔
287
            return;
288

289
        try
290
        {
291
            {
32✔
292
                std::lock_guard<queue_mutex_type> l(queue_mtx_);
32✔
293
                if (queue_.empty())
294
                    return;    // some other thread did the deed
295
            }
296

×
297
            if (!ensure_prefix())
298
                return;    // some other thread tries to do logging
299

×
300
            messages_type msgs;
301
            {
302
                std::lock_guard<queue_mutex_type> l(queue_mtx_);
×
303
                if (queue_.empty())
304
                    return;    // some other thread did the deed
305
                queue_.swap(msgs);
306
            }
307

×
308
            console_logging_locked(prefix_, msgs);
×
309
        }
×
310
        catch (...)
311
        {
312
            is_sending_ = false;
×
313
            throw;
×
314
        }
315

316
        is_sending_ = false;
317
    }
318

319
    ///////////////////////////////////////////////////////////////////////////
320
    namespace detail {
321

322
        struct pending_logs_tag
323
        {
324
        };
325

×
326
        pending_logs& logger()
327
        {
328
            util::reinitializable_static<pending_logs, pending_logs_tag> logs;
×
329
            return logs.get();
330
        }
331
    }    // namespace detail
332

×
333
    void console_logging(
334
        logging_destination dest, std::size_t level, std::string const& s)
335
    {
336
        message_type msg(dest, level, s);
×
337
        detail::logger().add(msg);
×
338
    }
339

32✔
340
    void cleanup_logging()
341
    {
32✔
342
        detail::logger().cleanup();
32✔
343
    }
344

32✔
345
    void activate_logging()
346
    {
347
        detail::logger().activate();
32✔
348
    }
349
}}    // namespace hpx::components
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc