• 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

64.71
/libs/core/init_runtime_local/src/init_runtime_local.cpp
1
//  Copyright (c) 2007-2025 Hartmut Kaiser
2
//  Copyright (c)      2017 Shoshana Jakobovits
3
//  Copyright (c) 2010-2011 Phillip LeBlanc, Dylan Stark
4
//  Copyright (c)      2011 Bryce Lelbach
5
//
6
//  SPDX-License-Identifier: BSL-1.0
7
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
8
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9

10
#include <hpx/assert.hpp>
11
#include <hpx/init_runtime_local/detail/init_logging.hpp>
12
#include <hpx/init_runtime_local/init_runtime_local.hpp>
13
#include <hpx/modules/algorithms.hpp>
14
#include <hpx/modules/command_line_handling_local.hpp>
15
#include <hpx/modules/errors.hpp>
16
#include <hpx/modules/execution.hpp>
17
#include <hpx/modules/executors.hpp>
18
#include <hpx/modules/filesystem.hpp>
19
#include <hpx/modules/format.hpp>
20
#include <hpx/modules/functional.hpp>
21
#include <hpx/modules/futures.hpp>
22
#include <hpx/modules/lock_registration.hpp>
23
#include <hpx/modules/logging.hpp>
24
#include <hpx/modules/program_options.hpp>
25
#include <hpx/modules/resource_partitioner.hpp>
26
#include <hpx/modules/runtime_local.hpp>
27
#include <hpx/modules/schedulers.hpp>
28
#include <hpx/modules/string_util.hpp>
29
#include <hpx/modules/testing.hpp>
30
#include <hpx/modules/threading.hpp>
31
#include <hpx/modules/threading_base.hpp>
32
#include <hpx/modules/timing.hpp>
33
#include <hpx/modules/type_support.hpp>
34

35
#if defined(HPX_NATIVE_MIC) || defined(__bgq__)
36
#include <cstdlib>
37
#endif
38

39
#include <cstddef>
40
#include <exception>
41
#include <functional>
42
#include <iostream>
43
#include <map>
44
#include <memory>
45
#include <string>
46
#include <utility>
47
#include <vector>
48

49
#if !defined(HPX_WINDOWS)
50
#include <signal.h>
51
#endif
52

53
///////////////////////////////////////////////////////////////////////////////
54
namespace hpx {
55

56
    void (*on_finalize)() = nullptr;
57

58
    namespace detail {
59

60
        int init_helper(hpx::program_options::variables_map& /*vm*/,
61
            hpx::function<int(int, char**)> const& f)
62
        {
63
            std::string cmdline(
64
                hpx::get_config_entry("hpx.reconstructed_cmd_line", ""));
65

66
            using namespace hpx::program_options;
67
#if defined(HPX_WINDOWS)
68
            std::vector<std::string> args = split_winmain(cmdline);
69
#else
70
            std::vector<std::string> args = split_unix(cmdline);
71
#endif
72

73
            // Copy all arguments which are not hpx related to a temporary array
74
            std::vector<char*> argv(args.size() + 1);
75
            std::size_t argcount = 0;
76
            for (std::size_t i = 0; i != args.size(); ++i)
77
            {
16✔
78
                if (0 != args[i].find("--hpx:"))
79
                {
80
                    argv[argcount++] = const_cast<char*>(args[i].data());
81
                }
32✔
82
                else if (6 == args[i].find("positional", 6))
83
                {
84
                    std::string::size_type const p = args[i].find_first_of('=');
85
                    if (p != std::string::npos)
86
                    {
87
                        args[i] = args[i].substr(p + 1);
32✔
88
                        argv[argcount++] = const_cast<char*>(args[i].data());
89
                    }
90
                }
91
            }
16✔
92

93
            // add a single nullptr in the end as some application rely on that
85✔
94
            argv[argcount] = nullptr;
95

69✔
96
            // Invoke custom startup functions
97
            return f(static_cast<int>(argcount), argv.data());
16✔
98
        }
99
    }    // namespace detail
53✔
100

101
    namespace local {
102

×
103
        // Print stack trace and exit.
104
#if defined(HPX_WINDOWS)
×
105
        extern BOOL WINAPI termination_handler(DWORD ctrl_type);
×
106
#else
107
        extern void termination_handler(int signum);
108
#endif
109

110
        int finalize(error_code& ec)
111
        {
16✔
112
            if (!threads::get_self_ptr())
113
            {
114
                HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::finalize",
32✔
115
                    "this function can be called from an HPX thread only");
16✔
116
                return -1;
117
            }
118

119
            if (!is_running())
120
            {
121
                HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::finalize",
122
                    "the runtime system is not active (did you already "
123
                    "call finalize?)");
124
                return -1;
125
            }
126

32✔
127
            if (&ec != &throws)
128
                ec = make_success_code();
32✔
129

130
            runtime* rt = get_runtime_ptr();
×
131
            if (nullptr == rt)
132
            {
×
133
                HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::finalize",
134
                    "the runtime system is not active (did you already "
135
                    "call hpx::stop?)");
32✔
136
                return -1;
137
            }
×
138

139
            rt->finalize(0);
140

×
141
            // invoke user supplied finalizer
142
            if (hpx::on_finalize != nullptr)
143
            {
32✔
144
                (*hpx::on_finalize)();
×
145
            }
146

32✔
147
            return 0;
32✔
148
        }
149

×
150
        int stop(error_code& ec)
151
        {
152
            if (threads::get_self_ptr())
×
153
            {
154
                HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::stop",
155
                    "this function cannot be called from an HPX thread");
32✔
156
                return -1;
157
            }
158

32✔
159
            std::unique_ptr<runtime> const rt(
160
                get_runtime_ptr());    // take ownership!
×
161
            if (!rt)
162
            {
163
                HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::stop",
164
                    "the runtime system is not active (did you already "
165
                    "call hpx::stop?)");
166
                return -1;
2✔
167
            }
168

2✔
169
            int const result = rt->wait();
170

×
171
            rt->stop();
172
            rt->rethrow_exception();
×
173

174
            return result;
175
        }
176

2✔
177
        ///////////////////////////////////////////////////////////////////////////
2✔
178
        int suspend(error_code& ec)
179
        {
×
180
            if (threads::get_self_ptr())
181
            {
182
                HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::suspend",
×
183
                    "this function cannot be called from an HPX thread");
184
                return -1;
185
            }
2✔
186

187
            runtime* rt = get_runtime_ptr();
2✔
188
            if (nullptr == rt)
2✔
189
            {
190
                HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::suspend",
191
                    "the runtime system is not active (did you already "
192
                    "call hpx::stop?)");
193
                return -1;
194
            }
×
195

196
            return rt->suspend();
×
197
        }
198

×
199
        ///////////////////////////////////////////////////////////////////////////
200
        int resume(error_code& ec)
×
201
        {
202
            if (threads::get_self_ptr())
203
            {
×
204
                HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::resume",
×
205
                    "this function cannot be called from an HPX thread");
206
                return -1;
×
207
            }
208

209
            runtime* rt = get_runtime_ptr();
×
210
            if (nullptr == rt)
211
            {
212
                HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::resume",
×
213
                    "the runtime system is not active (did you already "
214
                    "call hpx::stop?)");
215
                return -1;
216
            }
×
217

218
            return rt->resume();
×
219
        }
220

×
221
        ///////////////////////////////////////////////////////////////////////////
222
        namespace detail {
×
223

224
            ///////////////////////////////////////////////////////////////////////
225
            void activate_global_options(
×
226
                local::detail::command_line_handling& cmdline)
×
227
            {
228
#if defined(__linux) || defined(linux) || defined(__linux__) ||                \
×
229
    defined(__FreeBSD__)
230
                threads::coroutines::detail::posix::use_guard_pages =
231
                    cmdline.rtcfg_.use_stack_guard_pages();
×
232
#endif
233
#ifdef HPX_HAVE_VERIFY_LOCKS
234
                if (cmdline.rtcfg_.enable_lock_detection())
×
235
                {
236
                    util::enable_lock_detection();
237
                    util::trace_depth_lock_detection(
238
                        cmdline.rtcfg_.trace_depth());
239
                }
240
                else
241
                {
×
242
                    util::disable_lock_detection();
243
                }
244
#endif
245
#ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
246
                threads::policies::set_minimal_deadlock_detection_enabled(
32✔
247
                    cmdline.rtcfg_.enable_minimal_deadlock_detection());
×
248
#endif
249
#ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
250
                util::detail::set_spinlock_break_on_deadlock_enabled(
251
                    cmdline.rtcfg_.enable_spinlock_deadlock_detection());
252
                util::detail::set_spinlock_deadlock_detection_limit(
253
                    cmdline.rtcfg_.get_spinlock_deadlock_detection_limit());
254
#endif
255
#if defined(HPX_HAVE_LOGGING)
256
                util::detail::init_logging_local(cmdline.rtcfg_);
257
#else
258
                util::detail::warn_if_logging_requested(cmdline.rtcfg_);
259
#endif
260
            }
261

262
            ///////////////////////////////////////////////////////////////////////
263
            void add_startup_functions(hpx::runtime& rt,
264
                hpx::program_options::variables_map const& vm,
265
                startup_function_type startup, shutdown_function_type shutdown)
266
            {
267
                if (vm.count("hpx:app-config"))
268
                {
269
                    std::string const config(
270
                        vm["hpx:app-config"].as<std::string>());
271
                    rt.get_config().load_application_configuration(
272
                        config.c_str());
32✔
273
                }
274

275
                if (!!startup)
276
                    rt.add_startup_function(HPX_MOVE(startup));
32✔
277

278
                if (!!shutdown)
279
                    rt.add_shutdown_function(HPX_MOVE(shutdown));
32✔
280

281
                if (vm.count("hpx:dump-config-initial"))
282
                {
283
                    std::cout << "Configuration after runtime construction:\n";
64✔
284
                    std::cout << "-----------------------------------------\n";
285
                    rt.get_config().dump(0, std::cout);
×
286
                    std::cout << "-----------------------------------------\n";
×
287
                }
288

289
                if (vm.count("hpx:dump-config"))
290
                    rt.add_startup_function(dump_config(rt));
32✔
291
            }
×
292

293
            ///////////////////////////////////////////////////////////////////////
32✔
294
            int run(hpx::runtime& rt,
×
295
                hpx::function<int(
296
                    hpx::program_options::variables_map& vm)> const& f,
64✔
297
                hpx::program_options::variables_map& vm,
298
                startup_function_type startup, shutdown_function_type shutdown)
×
299
            {
×
300
                LPROGRESS_;
×
301

×
302
                add_startup_functions(
303
                    rt, vm, HPX_MOVE(startup), HPX_MOVE(shutdown));
304

64✔
305
                // Run this runtime instance using the given function f.
×
306
                if (!f.empty())
32✔
307
                    return rt.run(hpx::bind_front(f, vm));
308

309
                // Run this runtime instance without hpx_main
31✔
310
                return rt.run();
311
            }
312

313
            int start(hpx::runtime& rt,
314
                hpx::function<int(
315
                    hpx::program_options::variables_map& vm)> const& f,
31✔
316
                hpx::program_options::variables_map& vm,
317
                startup_function_type startup, shutdown_function_type shutdown)
62✔
318
            {
319
                LPROGRESS_;
320

321
                add_startup_functions(
31✔
322
                    rt, vm, HPX_MOVE(startup), HPX_MOVE(shutdown));
62✔
323

324
                if (!f.empty())
325
                {
×
326
                    // Run this runtime instance using the given function f.
327
                    return rt.start(hpx::bind_front(f, vm));
328
                }
1✔
329

330
                // Run this runtime instance without hpx_main
331
                return rt.start();
332
            }
333

334
            int run_or_start(bool blocking, std::unique_ptr<hpx::runtime> rt,
1✔
335
                local::detail::command_line_handling& cfg,
336
                startup_function_type startup, shutdown_function_type shutdown)
2✔
337
            {
338
                if (blocking)
339
                {
1✔
340
                    return run(*rt, cfg.hpx_main_f_, cfg.vm_, HPX_MOVE(startup),
341
                        HPX_MOVE(shutdown));
342
                }
2✔
343

344
                // non-blocking version
345
                int const result = start(*rt, cfg.hpx_main_f_, cfg.vm_,
346
                    HPX_MOVE(startup), HPX_MOVE(shutdown));
×
347

348
                // pointer to runtime is stored in TLS
349
                [[maybe_unused]] hpx::runtime const* p = rt.release();
32✔
350

351
                return result;
352
            }
353

32✔
354
            ////////////////////////////////////////////////////////////////////////
355
            void init_environment(
62✔
356
                [[maybe_unused]] hpx::util::runtime_configuration const& cfg)
357
            {
358
                HPX_UNUSED(hpx::filesystem::initial_path());
359

360
                hpx::assertion::set_assertion_handler(
2✔
361
                    &hpx::detail::assertion_handler);
362
                hpx::util::set_test_failure_handler(
363
                    &hpx::detail::test_failure_handler);
364
                hpx::set_custom_exception_info_handler(
365
                    &hpx::detail::custom_exception_info);
366
                hpx::serialization::detail::set_save_custom_exception_handler(
367
                    &hpx::runtime_local::detail::save_custom_exception);
1✔
368
                hpx::serialization::detail::set_load_custom_exception_handler(
369
                    &hpx::runtime_local::detail::load_custom_exception);
370
                hpx::set_pre_exception_handler(
371
                    &hpx::detail::pre_exception_handler);
32✔
372
                hpx::set_thread_termination_handler(
373
                    [](std::exception_ptr const& e) { report_error(e); });
32✔
374
                hpx::lcos::detail::set_run_on_completed_error_handler(
375
                    [](std::exception_ptr const& e) {
32✔
376
                        hpx::detail::report_exception_and_terminate(e);
377
                    });
32✔
378
#if defined(HPX_HAVE_VERIFY_LOCKS)
64✔
379
                hpx::util::set_registered_locks_error_handler(
64✔
380
                    &hpx::detail::registered_locks_error_handler);
381
                hpx::util::set_register_locks_predicate(
64✔
382
                    &hpx::detail::register_locks_predicate);
383
#endif
64✔
384
#if !defined(HPX_HAVE_DISABLED_SIGNAL_EXCEPTION_HANDLERS)
385
                set_error_handlers(cfg);
64✔
386
#endif
387
                hpx::threads::detail::set_get_default_pool(
64✔
388
                    &hpx::detail::get_default_pool);
×
389
                hpx::threads::detail::set_get_default_timer_service(
32✔
390
                    &hpx::detail::get_default_timer_service);
×
391
                hpx::threads::detail::set_get_locality_id(&get_locality_id);
×
392
                hpx::parallel::execution::detail::set_get_pu_mask(
393
                    &hpx::detail::get_pu_mask);
394
                hpx::parallel::execution::detail::set_get_os_thread_count(
395
                    []() { return hpx::get_os_thread_count(); });
396

397
#if defined(HPX_NATIVE_MIC) || defined(__bgq__) || defined(__bgqion__)
398
                unsetenv("LANG");
399
                unsetenv("LC_CTYPE");
400
                unsetenv("LC_NUMERIC");
32✔
401
                unsetenv("LC_TIME");
402
                unsetenv("LC_COLLATE");
32✔
403
                unsetenv("LC_MONETARY");
32✔
404
                unsetenv("LC_MESSAGES");
32✔
405
                unsetenv("LC_PAPER");
32✔
406
                unsetenv("LC_NAME");
32✔
407
                unsetenv("LC_ADDRESS");
32✔
408
                unsetenv("LC_TELEPHONE");
64✔
409
                unsetenv("LC_MEASUREMENT");
32✔
410
                unsetenv("LC_IDENTIFICATION");
×
411
                unsetenv("LC_ALL");
412
#endif
413
            }
414

415
            // make sure the runtime system is not active yet
416
            int ensure_no_runtime_is_up()
417
            {
418
                // make sure the runtime system is not active yet
419
                if (get_runtime_ptr() != nullptr)
420
                {
421
                    std::cerr << "hpx::init: can't initialize runtime system "
422
                                 "more than once! Exiting...\n";
423
                    return -1;
424
                }
425
                return 0;
426
            }
427

428
            ///////////////////////////////////////////////////////////////////////
32✔
429
            int run_or_start(
430
                hpx::function<int(
431
                    hpx::program_options::variables_map& vm)> const& f,
32✔
432
                int argc, char** argv, init_params const& params, bool blocking)
433
            {
434
                int result;
32✔
435
                try
436
                {
437
                    result = ensure_no_runtime_is_up();
×
438
                    if (result != 0)
×
439
                    {
440
                        return result;
441
                    }
442

443
                    hpx::local::detail::command_line_handling cmdline{
444
                        hpx::util::runtime_configuration(
32✔
445
                            argv[0], hpx::runtime_mode::local),
446
                        params.cfg, f};
447

448
                    // scope exception handling to resource partitioner initialization
449
                    // any exception thrown during run_or_start below are handled
32✔
450
                    // separately
451
                    try
452
                    {
453
                        result = cmdline.call(params.desc_cmdline, argc, argv);
454

32✔
455
                        init_environment(cmdline.rtcfg_);
456

×
457
                        hpx::threads::policies::detail::affinity_data
458
                            affinity_data{};
459
                        affinity_data.init(
460
                            hpx::util::get_entry_as<std::size_t>(
64✔
461
                                cmdline.rtcfg_, "hpx.os_threads", 0),
462
                            hpx::util::get_entry_as<std::size_t>(
96✔
463
                                cmdline.rtcfg_, "hpx.cores", 0),
464
                            hpx::util::get_entry_as<std::size_t>(
465
                                cmdline.rtcfg_, "hpx.pu_offset", 0),
466
                            hpx::util::get_entry_as<std::size_t>(
467
                                cmdline.rtcfg_, "hpx.pu_step", 0),
468
                            0, cmdline.rtcfg_.get_entry("hpx.affinity", ""),
469
                            cmdline.rtcfg_.get_entry("hpx.bind", ""),
32✔
470
                            hpx::util::get_entry_as<bool>(
471
                                cmdline.rtcfg_, "hpx.use_process_mask", false));
472

32✔
473
                        hpx::resource::partitioner rp =
128✔
474
                            hpx::resource::detail::make_partitioner(
64✔
475
                                params.rp_mode, cmdline.rtcfg_, affinity_data);
64✔
476

64✔
477
                        activate_global_options(cmdline);
64✔
478

64✔
479
                        // check whether HPX should be exited at this point
64✔
480
                        // (parse_result is returning a result > 0, if the program options
64✔
481
                        // contain --hpx:help or --hpx:version, on error result is < 0)
64✔
482
                        if (result != 0)
64✔
483
                        {
64✔
484
                            if (result > 0)
32✔
485
                                result = 0;
486
                            return result;
487
                        }
488

32✔
489
                        rp.assign_cores(hpx::util::get_entry_as<std::size_t>(
32✔
490
                            cmdline.rtcfg_, "hpx.first_used_core", 0));
491

492
                        // If thread_pools initialization in user main
493
                        if (params.rp_callback)
494
                        {
495
                            params.rp_callback(rp, cmdline.vm_);
496
                        }
32✔
497

498
                        // Setup all internal parameters of the resource_partitioner
×
499
                        rp.configure_pools();
500
                    }
501
                    catch (hpx::exception const& e)
502
                    {
503
                        std::cerr << "hpx::init: hpx::exception caught: "
32✔
504
                                  << hpx::get_error_what(e) << "\n";
64✔
505
                        return -1;
506
                    }
507

32✔
508
                    // Initialize and start the HPX runtime.
509
                    LPROGRESS_ << "run_local: create runtime";
510

511
                    // Build and configure this runtime instance.
512
                    std::unique_ptr<hpx::runtime> rt;
513

32✔
514
                    // Command line handling should have updated this by now.
32✔
515
                    LPROGRESS_ << "creating local runtime";
×
516
                    rt.reset(new hpx::runtime(cmdline.rtcfg_, true));
517

518
                    // Store application defined command line options
×
519
                    rt->set_app_options(params.desc_cmdline);
520

×
521
                    result = run_or_start(blocking, HPX_MOVE(rt), cmdline,
522
                        HPX_MOVE(params.startup), HPX_MOVE(params.shutdown));
523
                }
32✔
524
                catch (hpx::detail::command_line_error const& e)
525
                {
526
                    std::cerr << "hpx::local::init: std::exception caught: "
527
                              << e.what() << "\n";
528
                    return -1;
529
                }
32✔
530
                return result;
32✔
531
            }
532

533
            hpx::program_options::options_description const& default_desc(
534
                char const* desc)
535
            {
64✔
536
                static hpx::program_options::options_description default_desc_(
537
                    std::string("Usage: ") + desc + " [options]");
32✔
538
                return default_desc_;
×
539
            }
540
        }    // namespace detail
541
    }    // namespace local
×
542
}    // namespace hpx
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