• 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

41.15
/libs/full/init_runtime/src/hpx_init.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/config.hpp>
11
#include <hpx/hpx_init.hpp>
12

13
#include <hpx/assert.hpp>
14
#include <hpx/command_line_handling/command_line_handling.hpp>
15
#include <hpx/hpx_finalize.hpp>
16
#include <hpx/hpx_main_winsocket.hpp>
17
#include <hpx/hpx_suspend.hpp>
18
#include <hpx/hpx_user_main_config.hpp>
19
#include <hpx/modules/algorithms.hpp>
20
#include <hpx/modules/coroutines.hpp>
21
#include <hpx/modules/errors.hpp>
22
#include <hpx/modules/execution.hpp>
23
#include <hpx/modules/executors.hpp>
24
#include <hpx/modules/filesystem.hpp>
25
#include <hpx/modules/format.hpp>
26
#include <hpx/modules/functional.hpp>
27
#include <hpx/modules/futures.hpp>
28
#include <hpx/modules/init_runtime_local.hpp>
29
#include <hpx/modules/lock_registration.hpp>
30
#include <hpx/modules/logging.hpp>
31
#include <hpx/modules/prefix.hpp>
32
#include <hpx/modules/program_options.hpp>
33
#include <hpx/modules/resource_partitioner.hpp>
34
#include <hpx/modules/runtime_local.hpp>
35
#include <hpx/modules/schedulers.hpp>
36
#include <hpx/modules/string_util.hpp>
37
#include <hpx/modules/testing.hpp>
38
#include <hpx/modules/threading.hpp>
39
#include <hpx/modules/threading_base.hpp>
40
#include <hpx/modules/timing.hpp>
41
#include <hpx/modules/type_support.hpp>
42

43
#ifdef HPX_HAVE_MODULE_MPI_BASE
44
#include <hpx/modules/mpi_base.hpp>
45
#endif
46
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
47
#include <hpx/actions_base/plain_action.hpp>
48
#include <hpx/async_distributed/bind_action.hpp>
49
#include <hpx/components_base/agas_interface.hpp>
50
#include <hpx/init_runtime/detail/init_logging.hpp>
51
#include <hpx/init_runtime/pre_main.hpp>
52
#include <hpx/modules/async_distributed.hpp>
53
#include <hpx/modules/naming.hpp>
54
#if defined(HPX_HAVE_NETWORKING)
55
#include <hpx/parcelports/init_all_parcelports.hpp>
56
#include <hpx/parcelset/parcelhandler.hpp>
57
#include <hpx/parcelset_base/locality_interface.hpp>
58
#endif
59
#include <hpx/performance_counters/counters.hpp>
60
#include <hpx/performance_counters/query_counters.hpp>
61
#include <hpx/runtime_distributed.hpp>
62
#include <hpx/runtime_distributed/runtime_fwd.hpp>
63
#include <hpx/runtime_distributed/runtime_support.hpp>
64
#endif
65

66
#include <algorithm>
67
#include <cmath>
68
#include <cstddef>
69
#include <cstdlib>
70
#include <exception>
71
#include <functional>
72
#include <iostream>
73
#include <map>
74
#include <memory>
75
#include <sstream>
76
#include <string>
77
#include <utility>
78
#include <vector>
79

80
#if !defined(HPX_WINDOWS)
81
#include <signal.h>
82
#endif
83

84
#include <hpx/config/warnings_prefix.hpp>
85

86
///////////////////////////////////////////////////////////////////////////////
87
namespace hpx_startup {
88

89
    std::vector<std::string> (*user_main_config_function)(
90
        std::vector<std::string> const&) = nullptr;
91
}    // namespace hpx_startup
92

93
///////////////////////////////////////////////////////////////////////////////
94
namespace hpx::detail {
95

96
    // forward declarations only
97
    void console_print(std::string const&);
98

99
    int init_impl(
100
        hpx::function<int(hpx::program_options::variables_map&)> const& f,
101
        int argc, char** argv, init_params const& params,
102
        char const* hpx_prefix, [[maybe_unused]] char** env)
103
    {
104
        if (argc == 0 || argv == nullptr)
105
        {
106
            argc = hpx::local::detail::dummy_argc;
107
            argv = hpx::local::detail::dummy_argv;
108
        }
109

110
#if defined(HPX_WINDOWS)
31✔
111
        detail::init_winsocket();
112
#if defined(HPX_HAVE_APEX)
113
        // artificially force the apex shared library to be loaded by the
114
        // application
115
        apex::version();
31✔
116
#endif
117
#endif
×
118
#if defined(HPX_HAVE_NETWORKING)
×
119
        // force linking parcelports
120
        hpx::parcelset::init_all_parcelports();
121
#endif
122
        util::set_hpx_prefix(hpx_prefix);
123
#if defined(__FreeBSD__)
124
        freebsd_environ = env;
125
#endif
126
        // set a handler for std::at_quick_exit, and std::atexit
127
        [[maybe_unused]] auto const ret_at_exit = std::atexit(detail::on_exit);
128
        HPX_ASSERT(ret_at_exit == 0);
129

130
#if defined(HPX_HAVE_CXX11_STD_QUICK_EXIT)
131
        [[maybe_unused]] auto const ret_at_quick_exit =
31✔
132
            std::at_quick_exit(detail::on_exit);
133
        HPX_ASSERT(ret_at_quick_exit == 0);
31✔
134
#endif
135
        return detail::run_or_start(f, argc, argv, params, true);
136
    }
137

138
    bool start_impl(
139
        hpx::function<int(hpx::program_options::variables_map&)> const& f,
31✔
140
        int argc, char** argv, init_params const& params,
141
        char const* hpx_prefix, [[maybe_unused]] char** env)
142
    {
31✔
143
        if (argc == 0 || argv == nullptr)
144
        {
145
            argc = local::detail::dummy_argc;
146
            argv = local::detail::dummy_argv;
147
        }
31✔
148

149
#if defined(HPX_WINDOWS)
150
        detail::init_winsocket();
31✔
151
#if defined(HPX_HAVE_APEX)
152
        // artificially force the apex shared library to be loaded by the
153
        // application
1✔
154
        apex::version();
155
#endif
156
#endif
157
#if defined(HPX_HAVE_NETWORKING)
158
        // force linking parcelports
1✔
159
        hpx::parcelset::init_all_parcelports();
160
#endif
×
161
        util::set_hpx_prefix(hpx_prefix);
×
162
#if defined(__FreeBSD__)
163
        freebsd_environ = env;
164
#endif
165
        // set a handler for std::abort, std::at_quick_exit, and std::atexit
166
        [[maybe_unused]] auto const prev_signal =
167
            std::signal(SIGABRT, detail::on_abort);
168
        HPX_ASSERT(prev_signal != SIG_ERR);
169

170
        [[maybe_unused]] auto const ret_atexit = std::atexit(detail::on_exit);
171
        HPX_ASSERT(ret_atexit == 0);
172

173
#if defined(HPX_HAVE_CXX11_STD_QUICK_EXIT)
174
        [[maybe_unused]] auto const ret_at_quick_exit =
1✔
175
            std::at_quick_exit(detail::on_exit);
176
        HPX_ASSERT(ret_at_quick_exit == 0);
1✔
177
#endif
178
        return 0 == detail::run_or_start(f, argc, argv, params, false);
179
    }
180
}    // namespace hpx::detail
181

182
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
1✔
183
namespace hpx::detail {
184

185
    // forward declarations only
1✔
186
    void list_symbolic_name(std::string const&, hpx::id_type const&);
187
    void list_component_type(std::string const&, components::component_type);
188
}    // namespace hpx::detail
189

190
HPX_PLAIN_ACTION_ID(hpx::detail::console_print, console_print_action,
1✔
191
    hpx::actions::console_print_action_id)
192
HPX_PLAIN_ACTION_ID(hpx::detail::list_component_type,
193
    list_component_type_action, hpx::actions::list_component_type_action_id)
1✔
194

195
using bound_list_component_type_action =
196
    hpx::detail::bound_action<list_component_type_action,
197
        hpx::util::index_pack<0, 1, 2>, hpx::id_type,
198
        hpx::detail::placeholder<1>, hpx::detail::placeholder<2>>;
199

200
HPX_UTIL_REGISTER_FUNCTION_DECLARATION(
201
    void(std::string const&, hpx::components::component_type),
202
    bound_list_component_type_action, list_component_type_function)
203

204
HPX_UTIL_REGISTER_FUNCTION(
205
    void(std::string const&, hpx::components::component_type),
×
206
    bound_list_component_type_action, list_component_type_function)
207
#endif
×
208

209
namespace hpx::detail {
210

211
    ///////////////////////////////////////////////////////////////////////////
212
    // print string on the console
213
    void console_print(std::string const& name)
214
    {
215
        std::cout << name << std::endl;
216
    }
217

218
    inline void print(std::string const& name, error_code& ec = throws)
219
    {
64✔
220
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
221
        hpx::id_type console(agas::get_console_locality(ec));
222
        if (ec)
223
            return;
224

225
        hpx::async<console_print_action>(console, name).get(ec);
226
        if (ec)
227
            return;
228
#else
×
229
        console_print(name);
230
#endif
231
        if (&ec != &throws)
×
232
            ec = make_success_code();
233
    }
×
234

235
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
236
    ///////////////////////////////////////////////////////////////////////////
×
237
    // redirect the printing of the given counter name to the console
×
238
    bool list_counter(
239
        performance_counters::counter_info const& info, error_code& ec)
240
    {
×
241
        print(info.fullname_, ec);
×
242
        return true;
243
    }
244

245
    // List the names of all registered performance counters.
246
    void list_counter_names_header(bool skeleton)
×
247
    {
×
248
        // print header
249
        print("List of available counter instances");
250
        if (skeleton)
251
            print("(replace '*' below with the appropriate sequence number)");
252
        print(std::string(78, '-'));
253
    }
×
254

255
    void list_counter_names_minimal()
256
    {
×
257
        // list all counter names
×
258
        list_counter_names_header(true);
259
        performance_counters::discover_counter_types(&list_counter,
260
            performance_counters::discover_counters_mode::minimal);
261
    }
×
262

263
    void list_counter_names_full()
264
    {
×
265
        // list all counter names
×
266
        list_counter_names_header(false);
×
267
        performance_counters::discover_counter_types(
×
268
            &list_counter, performance_counters::discover_counters_mode::full);
×
269
    }
270

×
271
    ///////////////////////////////////////////////////////////////////////////
272
    // redirect the printing of the full counter info to the console
273
    bool list_counter_info(
×
274
        performance_counters::counter_info const& info, error_code& ec)
×
275
    {
276
        // compose the information to be printed for each of the counters
×
277
        std::ostringstream strm;
278

×
279
        strm << std::string(78, '-') << '\n';
280
        strm << "fullname: " << info.fullname_ << '\n';
281
        strm << "helptext: " << info.helptext_ << '\n';
×
282
        strm << "type:     "
×
283
             << performance_counters::get_counter_type_name(info.type_) << '\n';
×
284

×
285
        strm << "version:  ";    // 0xMMmmrrrr
286
        hpx::util::format_to(strm, "{}.{}.{}\n", info.version_ / 0x1000000,
287
            info.version_ / 0x10000 % 0x100, info.version_ % 0x10000);
288
        strm << std::string(78, '-') << '\n';
×
289

290
        print(strm.str(), ec);
291

292
        if (&ec != &throws)
×
293
            ec = make_success_code();
294
        return true;
×
295
    }
×
296

×
297
    // List the names of all registered performance counters.
298
    void list_counter_infos_header(bool skeleton)
×
299
    {
300
        // print header
×
301
        print("Information about available counter instances");
×
302
        if (skeleton)
×
303
            print("(replace '*' below with the appropriate sequence number)");
×
304
        print("--------------------------------------------------------");
305
    }
×
306

307
    void list_counter_infos_minimal()
×
308
    {
×
309
        // list all counter information
×
310
        list_counter_infos_header(true);
×
311
        performance_counters::discover_counter_types(&list_counter_info,
312
            performance_counters::discover_counters_mode::minimal);
313
    }
×
314

315
    void list_counter_infos_full()
316
    {
×
317
        // list all counter information
×
318
        list_counter_infos_header(false);
×
319
        performance_counters::discover_counter_types(&list_counter_info,
×
320
            performance_counters::discover_counters_mode::full);
×
321
    }
322

×
323
    ///////////////////////////////////////////////////////////////////////////
324
    void list_symbolic_name(std::string const& name, hpx::id_type const& id)
325
    {
×
326
        std::string const str = hpx::util::format("{}, {}, {}", name, id,
×
327
            (id.get_management_type() == id_type::management_type::managed ?
328
                    "management_type::managed" :
×
329
                    "management_type::unmanaged"));
330
        print(str);
×
331
    }
332

333
    void list_symbolic_names()
×
334
    {
×
335
        print(std::string("List of all registered symbolic names:"));
336
        print(std::string("--------------------------------------"));
×
337

338
        std::map<std::string, hpx::id_type> const entries =
339
            agas::find_symbols(hpx::launch::sync);
×
340

341
        for (auto const& e : entries)
342
        {
×
343
            list_symbolic_name(e.first, e.second);
344
        }
×
345
    }
×
346

×
347
    ///////////////////////////////////////////////////////////////////////////
348
    void list_component_type(
×
349
        std::string const& name, components::component_type ctype)
350
    {
×
351
        print(hpx::util::format(
×
352
            "{1:-40}, {2}", name, components::get_component_type_name(ctype)));
353
    }
354

×
355
    void list_component_types()
356
    {
×
357
        print(std::string("List of all registered component types:"));
358
        print(std::string("---------------------------------------"));
×
359

360
        using hpx::placeholders::_1;
×
361
        using hpx::placeholders::_2;
362

363
        hpx::id_type console(agas::get_console_locality());
×
364
        naming::get_agas_client().iterate_types(
365
            hpx::bind<list_component_type_action>(console, _1, _2));
366
    }
×
367

×
368
    ///////////////////////////////////////////////////////////////////////////
×
369
    void start_counters(std::shared_ptr<util::query_counters> const& qc)
370
    {
×
371
        try
372
        {
×
373
            HPX_ASSERT(qc);
×
374
            qc->start();
375
        }
376
        catch (...)
377
        {
378
            std::cerr << hpx::diagnostic_information(std::current_exception())
×
379
                      << std::flush;
×
380
            hpx::terminate();
×
381
        }
×
382
    }
383
#endif
384
}    // namespace hpx::detail
×
385

386
///////////////////////////////////////////////////////////////////////////////
387
#if defined(HPX_HAVE_DYNAMIC_HPX_MAIN) &&                                      \
388
    (defined(__linux) || defined(__linux__) || defined(linux) ||               \
389
        defined(__APPLE__))
×
390
namespace hpx_start {
391
    // Importing weak symbol from libhpx_wrap.a which may be shadowed by one present in
×
392
    // hpx_main.hpp.
393
    HPX_SYMBOL_EXPORT __attribute__((weak)) bool include_libhpx_wrap = false;
×
394
}    // namespace hpx_start
395

×
396
#endif
×
397

×
398
///////////////////////////////////////////////////////////////////////////////
399
namespace hpx {
400

401
    // Print stack trace and exit.
402
#if defined(HPX_WINDOWS)
403
    extern BOOL WINAPI termination_handler(DWORD ctrl_type);
404
#else
405
    extern void termination_handler(int signum);
406
#endif
407

408
    ///////////////////////////////////////////////////////////////////////////
409
    namespace detail {
410

411
        ///////////////////////////////////////////////////////////////////////
412
        void activate_global_options(
413
            util::command_line_handling& cmdline, int argc, char** argv)
414
        {
415
#if defined(__linux) || defined(linux) || defined(__linux__) ||                \
416
    defined(__FreeBSD__)
417
            threads::coroutines::detail::posix::use_guard_pages =
418
                cmdline.rtcfg_.use_stack_guard_pages();
419
#endif
420
#ifdef HPX_HAVE_VERIFY_LOCKS
421
            if (cmdline.rtcfg_.enable_lock_detection())
422
            {
423
                util::enable_lock_detection();
424
                util::trace_depth_lock_detection(cmdline.rtcfg_.trace_depth());
425
            }
426
            else
427
            {
32✔
428
                util::disable_lock_detection();
429
            }
430
#endif
431
#ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
432
            threads::policies::set_minimal_deadlock_detection_enabled(
32✔
433
                cmdline.rtcfg_.enable_minimal_deadlock_detection());
32✔
434
#endif
435
#ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
436
            util::detail::set_spinlock_break_on_deadlock_enabled(
437
                cmdline.rtcfg_.enable_spinlock_deadlock_detection());
438
            util::detail::set_spinlock_deadlock_detection_limit(
439
                cmdline.rtcfg_.get_spinlock_deadlock_detection_limit());
440
#endif
441

442
#if defined(HPX_HAVE_LOGGING)
443
            util::detail::init_logging_full(cmdline.rtcfg_);
444
#else
445
            util::detail::warn_if_logging_requested(cmdline.rtcfg_);
446
#endif
447

448
#if defined(HPX_HAVE_NETWORKING)
449
            if (cmdline.num_localities_ != 1 || cmdline.node_ != 0 ||
450
                cmdline.rtcfg_.enable_networking())
451
            {
452
                parcelset::parcelhandler::init(&argc, &argv, cmdline);
453
            }
454
#endif
455
            HPX_UNUSED(argc);
456
            HPX_UNUSED(argv);
457
        }
458

32✔
459
        ///////////////////////////////////////////////////////////////////////
460
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
461
        void handle_list_and_print_options(hpx::runtime& rt,
462
            hpx::program_options::variables_map& vm,
463
            bool print_counters_locally)
464
        {
58✔
465
            auto* rtd = dynamic_cast<hpx::runtime_distributed*>(&rt);
26✔
466
            if (rtd == nullptr)
467
            {
6✔
468
                throw detail::command_line_error(
469
                    "Unexpected: runtime system was not initialized.");
470
            }
471

472
            if (vm.count("hpx:list-counters"))
32✔
473
            {
474
                // Print the names of all registered performance counters.
475
                std::string option(vm["hpx:list-counters"].as<std::string>());
476
                if (0 == std::string("minimal").find(option))
29✔
477
                    rt.add_startup_function(&list_counter_names_minimal);
478
                else if (0 == std::string("full").find(option))
479
                    rt.add_startup_function(&list_counter_names_full);
480
                else
29✔
481
                {
29✔
482
                    std::string msg("Invalid command line option value"
483
                                    "for --hpx:list-counters: ");
484
                    msg += option;
×
485
                    msg += ", allowed values are 'minimal' and 'full'";
486
                    throw detail::command_line_error(msg.c_str());
487
                }
58✔
488
            }
489
            if (vm.count("hpx:list-counter-infos"))
490
            {
×
491
                // Print info about all registered performance counters.
×
492
                std::string option(
×
493
                    vm["hpx:list-counter-infos"].as<std::string>());
×
494
                if (0 == std::string("minimal").find(option))
×
495
                    rt.add_startup_function(&list_counter_infos_minimal);
496
                else if (0 == std::string("full").find(option))
497
                    rt.add_startup_function(&list_counter_infos_full);
498
                else
×
499
                {
500
                    std::string msg("Invalid command line option value"
501
                                    "for --hpx:list-counter-infos: ");
×
502
                    msg += option;
503
                    msg += ", allowed values are 'minimal' and 'full'";
504
                    throw detail::command_line_error(msg.c_str());
58✔
505
                }
506
            }
507
            if (vm.count("hpx:list-symbolic-names"))
508
            {
×
509
                // Print all registered symbolic names.
×
510
                rt.add_startup_function(&list_symbolic_names);
×
511
            }
×
512
            if (vm.count("hpx:list-component-types"))
×
513
            {
514
                // Print all registered component types.
515
                rt.add_startup_function(&list_component_types);
516
            }
×
517

518
            if (vm.count("hpx:print-counter") ||
519
                vm.count("hpx:print-counter-reset"))
×
520
            {
521
                std::size_t interval = 0;
522
                if (vm.count("hpx:print-counter-interval"))
58✔
523
                {
524
                    interval =
525
                        vm["hpx:print-counter-interval"].as<std::size_t>();
×
526
                }
527

58✔
528
                std::vector<std::string> counters;
529
                if (vm.count("hpx:print-counter"))
530
                {
×
531
                    counters =
532
                        vm["hpx:print-counter"].as<std::vector<std::string>>();
533
                }
58✔
534

87✔
535
                std::vector<std::string> reset_counters;
536
                if (vm.count("hpx:print-counter-reset"))
×
537
                {
×
538
                    reset_counters = vm["hpx:print-counter-reset"]
539
                                         .as<std::vector<std::string>>();
×
540
                }
×
541

542
                std::vector<std::string> counter_shortnames;
543
                std::string counter_format("normal");
×
544
                if (vm.count("hpx:print-counter-format"))
×
545
                {
546
                    counter_format =
547
                        vm["hpx:print-counter-format"].as<std::string>();
×
548
                    if (counter_format == "csv-short")
549
                    {
550
                        for (auto& counter : counters)
×
551
                        {
×
552
                            std::vector<std::string> entry;
553
                            hpx::string_util::split(entry, counter,
×
554
                                hpx::string_util::is_any_of(","),
×
555
                                hpx::string_util::token_compress_mode::on);
556

557
                            if (entry.size() != 2)
×
558
                            {
×
559
                                throw detail::command_line_error(
×
560
                                    "Invalid format for command line "
561
                                    "option "
562
                                    "--hpx:print-counter-format=csv-short");
×
563
                            }
×
564

565
                            counter_shortnames.push_back(entry[0]);
×
566
                            counter = entry[1];
567
                        }
×
568
                    }
×
569
                }
×
570

571
                bool csv_header = true;
572
                if (vm.count("hpx:no-csv-header"))
×
573
                    csv_header = false;
574

575
                std::string destination("cout");
576
                if (vm.count("hpx:print-counter-destination"))
577
                    destination =
×
578
                        vm["hpx:print-counter-destination"].as<std::string>();
579

580
                bool counter_types = false;
×
581
                if (vm.count("hpx:print-counter-types"))
582
                    counter_types = true;
×
583

584
                // schedule the query function at startup, which will schedule
585
                // itself to run after the given interval
586
                std::shared_ptr<util::query_counters> qc =
×
587
                    std::make_shared<util::query_counters>(std::ref(counters),
×
588
                        std::ref(reset_counters), interval, destination,
×
589
                        counter_format, counter_shortnames, csv_header,
590
                        print_counters_locally, counter_types);
×
591

×
592
                // schedule to print counters at shutdown, if requested
593
                if (get_config_entry("hpx.print_counter.shutdown", "0") == "1")
×
594
                {
595
                    // schedule to run at shutdown
×
596
                    rt.add_pre_shutdown_function(hpx::bind_front(
×
597
                        &util::query_counters::evaluate, qc, true));
×
598
                }
599

600
                // schedule to start all counters
601

602
                rt.add_startup_function(hpx::bind_front(&start_counters, qc));
×
603

×
604
                // register the query_counters object with the runtime system
605
                rtd->register_query_counters(qc);
606
            }
607
            else if (vm.count("hpx:print-counter-interval"))
608
            {
×
609
                throw detail::command_line_error(
610
                    "Invalid command line option "
611
                    "--hpx:print-counter-interval, valid in conjunction "
×
612
                    "with --hpx:print-counter only");
613
            }
614
            else if (vm.count("hpx:print-counter-destination"))
615
            {
616
                throw detail::command_line_error(
617
                    "Invalid command line option "
×
618
                    "--hpx:print-counter-destination, valid in conjunction "
619
                    "with --hpx:print-counter only");
620
            }
×
621
            else if (vm.count("hpx:print-counter-format"))
×
622
            {
58✔
623
                throw detail::command_line_error(
624
                    "Invalid command line option "
625
                    "--hpx:print-counter-format, valid in conjunction with "
626
                    "--hpx:print-counter only");
627
            }
×
628
            else if (vm.count("hpx:print-counter-at"))
629
            {
58✔
630
                throw detail::command_line_error(
631
                    "Invalid command line option "
632
                    "--hpx:print-counter-at, valid in conjunction with "
633
                    "--hpx:print-counter only");
634
            }
×
635
            else if (vm.count("hpx:reset-counters"))
636
            {
58✔
637
                throw detail::command_line_error(
638
                    "Invalid command line option "
639
                    "--hpx:reset-counters, valid in conjunction with "
640
                    "--hpx:print-counter only");
641
            }
×
642
        }
643
#endif
58✔
644

645
        void add_startup_functions(hpx::runtime& rt,
646
            hpx::program_options::variables_map& vm, runtime_mode mode,
647
            startup_function_type startup, shutdown_function_type shutdown)
648
        {
×
649
            if (vm.count("hpx:app-config"))
650
            {
58✔
651
                std::string const config(
652
                    vm["hpx:app-config"].as<std::string>());
653
                rt.get_config().load_application_configuration(config.c_str());
654
            }
655

×
656
            if (!!startup)
657
                rt.add_startup_function(HPX_MOVE(startup));
29✔
658

659
            if (!!shutdown)
660
                rt.add_shutdown_function(HPX_MOVE(shutdown));
32✔
661

662
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
663
            // Add startup function related to listing counter names or counter
664
            // infos (on console only).
64✔
665
            bool const print_counters_locally =
666
                vm.count("hpx:print-counters-locally") != 0;
667
            if (mode == runtime_mode::console || print_counters_locally)
×
668
                handle_list_and_print_options(rt, vm, print_counters_locally);
×
669
#else
670
            HPX_UNUSED(mode);
671
#endif
32✔
672

×
673
            // Dump the configuration before all components have been loaded.
674
            if (vm.count("hpx:dump-config-initial"))
32✔
675
            {
×
676
                std::cout << "Configuration after runtime construction:\n";
677
                std::cout << "-----------------------------------------\n";
678
                rt.get_config().dump(0, std::cout);
679
                std::cout << "-----------------------------------------\n";
680
            }
681

64✔
682
            // Dump the configuration after all components have been loaded.
32✔
683
            if (vm.count("hpx:dump-config"))
29✔
684
                rt.add_startup_function(hpx::local::detail::dump_config(rt));
685
        }
686

687
        ///////////////////////////////////////////////////////////////////////
688
        int run(hpx::runtime& rt,
689
            hpx::function<int(hpx::program_options::variables_map& vm)> const&
64✔
690
                f,
691
            hpx::program_options::variables_map& vm, runtime_mode mode,
×
692
            startup_function_type startup, shutdown_function_type shutdown)
×
693
        {
×
694
            LPROGRESS_;
×
695

696
            add_startup_functions(
697
                rt, vm, mode, HPX_MOVE(startup), HPX_MOVE(shutdown));
698

64✔
699
            // Run this runtime instance using the given function f.
×
700
            if (!f.empty())
32✔
701
                return rt.run(hpx::bind_front(f, vm));
702

703
            // Run this runtime instance without a hpx_main
31✔
704
            return rt.run();
705
        }
706

707
        int start(hpx::runtime& rt,
708
            hpx::function<int(hpx::program_options::variables_map& vm)> const&
709
                f,
31✔
710
            hpx::program_options::variables_map& vm, runtime_mode mode,
711
            startup_function_type startup, shutdown_function_type shutdown)
62✔
712
        {
713
            LPROGRESS_;
714

715
            add_startup_functions(
31✔
716
                rt, vm, mode, HPX_MOVE(startup), HPX_MOVE(shutdown));
56✔
717

718
            if (!f.empty())
719
            {
3✔
720
                // Run this runtime instance using the given function f.
721
                return rt.start(hpx::bind_front(f, vm));
722
            }
1✔
723

724
            // Run this runtime instance without a hpx_main
725
            return rt.start();
726
        }
727

728
        int run_or_start(bool blocking, std::unique_ptr<hpx::runtime> rt,
1✔
729
            util::command_line_handling& cfg, startup_function_type startup,
730
            shutdown_function_type shutdown)
2✔
731
        {
732
            if (blocking)
733
            {
1✔
734
                return run(*rt, cfg.hpx_main_f_, cfg.vm_, cfg.rtcfg_.mode_,
735
                    HPX_MOVE(startup), HPX_MOVE(shutdown));
736
            }
2✔
737

738
            // non-blocking version
739
            start(*rt, cfg.hpx_main_f_, cfg.vm_, cfg.rtcfg_.mode_,
740
                HPX_MOVE(startup), HPX_MOVE(shutdown));
×
741

742
            // pointer to runtime is stored in TLS
743
            [[maybe_unused]] hpx::runtime const* p = rt.release();
32✔
744
            HPX_ASSERT(p != nullptr);
745

746
            return 0;
747
        }
32✔
748

749
        ////////////////////////////////////////////////////////////////////////
62✔
750
        void init_environment(
751
            [[maybe_unused]] hpx::util::runtime_configuration const& cfg)
752
        {
753
            HPX_UNUSED(hpx::filesystem::initial_path());
754

2✔
755
            hpx::assertion::set_assertion_handler(&detail::assertion_handler);
756
            hpx::util::set_test_failure_handler(&detail::test_failure_handler);
757
#if defined(HPX_HAVE_APEX)
758
            hpx::util::set_enable_parent_task_handler(
759
                &detail::enable_parent_task_handler);
760
#endif
761
            hpx::set_custom_exception_info_handler(
1✔
762
                &detail::custom_exception_info);
763
            hpx::serialization::detail::set_save_custom_exception_handler(
764
                &runtime_local::detail::save_custom_exception);
765
            hpx::serialization::detail::set_load_custom_exception_handler(
32✔
766
                &runtime_local::detail::load_custom_exception);
767
            hpx::set_pre_exception_handler(&detail::pre_exception_handler);
32✔
768
            hpx::set_thread_termination_handler(
769
                [](std::exception_ptr const& e) { report_error(e); });
32✔
770
            hpx::lcos::detail::set_run_on_completed_error_handler(
64✔
771
                [](std::exception_ptr const& e) {
772
                    report_exception_and_terminate(e);
773
                });
774
#if defined(HPX_HAVE_VERIFY_LOCKS)
775
            hpx::util::set_registered_locks_error_handler(
64✔
776
                &detail::registered_locks_error_handler);
777
            hpx::util::set_register_locks_predicate(
64✔
778
                &detail::register_locks_predicate);
779
#endif
64✔
780
#if !defined(HPX_HAVE_DISABLED_SIGNAL_EXCEPTION_HANDLERS)
781
            set_error_handlers(cfg);
64✔
782
#endif
64✔
783
            hpx::threads::detail::set_get_default_pool(
×
784
                &detail::get_default_pool);
32✔
785
            hpx::threads::detail::set_get_default_timer_service(
×
786
                &hpx::detail::get_default_timer_service);
×
787
            hpx::threads::detail::set_get_locality_id(&get_locality_id);
788
            hpx::parallel::execution::detail::set_get_pu_mask(
789
                &hpx::detail::get_pu_mask);
790
            hpx::parallel::execution::detail::set_get_os_thread_count(
791
                []() { return hpx::get_os_thread_count(); });
792
            hpx::parallel::detail::set_exception_list_termination_handler(
793
                &hpx::terminate);
794
            hpx::parallel::util::detail::
795
                set_parallel_exception_termination_handler(&hpx::terminate);
32✔
796

797
            // instantiate the interface function initialization objects
32✔
798
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
32✔
799
#if defined(HPX_HAVE_NETWORKING)
32✔
800
            parcelset::locality_init();
32✔
801
#endif
32✔
802
            agas::agas_init();
32✔
803
            agas::runtime_components_init();
64✔
804
            components::counter_init();
32✔
805
#endif
×
806

32✔
807
#if defined(HPX_NATIVE_MIC) || defined(__bgq__) || defined(__bgqion__)
32✔
808
            unsetenv("LANG");
809
            unsetenv("LC_CTYPE");
32✔
810
            unsetenv("LC_NUMERIC");
811
            unsetenv("LC_TIME");
812
            unsetenv("LC_COLLATE");
813
            unsetenv("LC_MONETARY");
814
            unsetenv("LC_MESSAGES");
32✔
815
            unsetenv("LC_PAPER");
816
            unsetenv("LC_NAME");
32✔
817
            unsetenv("LC_ADDRESS");
32✔
818
            unsetenv("LC_TELEPHONE");
32✔
819
            unsetenv("LC_MEASUREMENT");
820
            unsetenv("LC_IDENTIFICATION");
821
            unsetenv("LC_ALL");
822
#endif
823
        }
824

825
        // make sure the runtime system is not active yet
826
        int ensure_no_runtime_is_up()
827
        {
828
            // make sure the runtime system is not active yet
829
            if (get_runtime_ptr() != nullptr)
830
            {
831
#if defined(HPX_HAVE_DYNAMIC_HPX_MAIN) &&                                      \
832
    (defined(__linux) || defined(__linux__) || defined(linux) ||               \
833
        defined(__APPLE__))
834
                // make sure the runtime system is not initialized
835
                // after its activation from int main()
836
                if (hpx_start::include_libhpx_wrap)
837
                {
32✔
838
                    std::cerr
839
                        << "hpx is already initialized from main.\n"
840
                           "Note: Delete hpx_main.hpp to initialize hpx system "
32✔
841
                           "using hpx::init. Exiting...\n";
842
                    return -1;
843
                }
32✔
844
#endif
845
                std::cerr << "hpx::init: can't initialize runtime system "
846
                             "more than once! Exiting...\n";
847
                return -1;
848
            }
849
            return 0;
850
        }
×
851

852
        ///////////////////////////////////////////////////////////////////////
853
        int run_or_start(
854
            hpx::function<int(hpx::program_options::variables_map& vm)> const&
855
                f,
×
856
            int argc, char** argv, init_params const& params, bool blocking)
×
857
        {
858
            int result;
859
            try
860
            {
×
861
                // make sure the runtime system is not active yet
×
862
                result = ensure_no_runtime_is_up();
863
                if (result != 0)
864
                {
865
                    return result;
866
                }
867

32✔
868
#if defined(HPX_HAVE_NETWORKING)
869
                hpx::util::command_line_handling cmdline{
870
                    hpx::util::runtime_configuration(argv[0], params.mode,
871
                        hpx::parcelset::load_runtime_configuration()),
872
                    hpx_startup::user_main_config(params.cfg), f};
32✔
873
#else
874
                hpx::util::command_line_handling cmdline{
875
                    hpx::util::runtime_configuration(argv[0], params.mode, {}),
876
                    hpx_startup::user_main_config(params.cfg), f};
877
#endif
878

32✔
879
                std::vector<
880
                    std::shared_ptr<components::component_registry_base>>
×
881
                    component_registries;
882

883
                // scope exception handling to resource partitioner initialization
884
                // any exception thrown during run_or_start below are handled
885
                // separately
32✔
886
                try
64✔
887
                {
96✔
888
                    result = cmdline.call(
889
                        params.desc_cmdline, argc, argv, component_registries);
890

891
                    init_environment(cmdline.rtcfg_);
892

893
                    hpx::threads::policies::detail::affinity_data
894
                        affinity_data{};
895
                    affinity_data.init(hpx::util::get_entry_as<std::size_t>(
896
                                           cmdline.rtcfg_, "hpx.os_threads", 0),
32✔
897
                        hpx::util::get_entry_as<std::size_t>(
898
                            cmdline.rtcfg_, "hpx.cores", 0),
899
                        hpx::util::get_entry_as<std::size_t>(
900
                            cmdline.rtcfg_, "hpx.pu_offset", 0),
901
                        hpx::util::get_entry_as<std::size_t>(
902
                            cmdline.rtcfg_, "hpx.pu_step", 0),
903
                        static_cast<std::size_t>(
32✔
904
                            cmdline.rtcfg_.get_first_used_core()),
905
                        cmdline.rtcfg_.get_entry("hpx.affinity", ""),
906
                        cmdline.rtcfg_.get_entry("hpx.bind", ""),
907
                        hpx::util::get_entry_as<bool>(
32✔
908
                            cmdline.rtcfg_, "hpx.use_process_mask", false));
128✔
909

64✔
910
                    hpx::resource::partitioner rp =
64✔
911
                        hpx::resource::detail::make_partitioner(
64✔
912
                            params.rp_mode, cmdline.rtcfg_, affinity_data);
64✔
913

64✔
914
                    activate_global_options(cmdline, argc, argv);
64✔
915

64✔
916
                    // check whether HPX should be exited at this point
917
                    // (parse_result is returning a result > 0, if the program options
32✔
918
                    // contain --hpx:help or --hpx:version, on error result is < 0)
64✔
919
                    if (result != 0)
64✔
920
                    {
32✔
921
                        result = (std::min) (result, 0);
32✔
922
                        return result;
923
                    }
924

32✔
925
                    // If thread_pools initialization in user main
32✔
926
                    if (params.rp_callback)
927
                    {
32✔
928
                        params.rp_callback(rp, cmdline.vm_);
929
                    }
930

931
#if defined(HPX_HAVE_NETWORKING)
932
                    if (cmdline.num_localities_ != 1 || cmdline.node_ != 0 ||
32✔
933
                        cmdline.rtcfg_.enable_networking())
934
                    {
×
935
                        parcelset::parcelhandler::init(rp);
936
                    }
937
#endif
938
                    // Setup all internal parameters of the resource_partitioner
939
                    rp.configure_pools();
940
                }
32✔
941
                catch (hpx::exception const& e)
942
                {
943
                    std::cerr << "hpx::init: hpx::exception caught: "
944
                              << hpx::get_error_what(e) << "\n";
945
                    return -1;
946
                }
58✔
947

26✔
948
                // Initialize and start the HPX runtime.
949
                LPROGRESS_ << "run_local: create runtime";
6✔
950

951
                // Build and configure this runtime instance.
952
                std::unique_ptr<hpx::runtime> rt;
953

32✔
954
                // Command line handling should have updated this by now.
32✔
955
                HPX_ASSERT(cmdline.rtcfg_.mode_ != runtime_mode::default_);
×
956
                if (cmdline.rtcfg_.mode_ == runtime_mode::local)
957
                {
958
                    LPROGRESS_ << "creating local runtime";
×
959
                    rt.reset(new hpx::runtime(cmdline.rtcfg_, true));
960
                }
×
961
                else
962
                {
963
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
32✔
964
                    for (auto const& registry : component_registries)
965
                    {
966
                        hpx::register_startup_function([registry]() {
967
                            registry->register_component_type();
968
                        });
969
                    }
970

32✔
971
                    LPROGRESS_ << "creating distributed runtime";
972
                    rt.reset(new hpx::runtime_distributed(cmdline.rtcfg_,
×
973
                        &hpx::detail::pre_main, &hpx::detail::post_main));
974
#else
×
975
                    HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
976
                        "run_or_start",
977
                        "Attempted to start the runtime in the mode \"{1}\", "
978
                        "but HPX was compiled with "
32✔
979
                        "HPX_WITH_DISTRIBUTED_RUNTIME=OFF, and \"{1}\" "
980
                        "requires HPX_WITH_DISTRIBUTED_RUNTIME=ON. "
981
                        "Recompile HPX with HPX_WITH_DISTRIBUTED_RUNTIME=ON or "
64✔
982
                        "change the runtime mode.",
983
                        get_runtime_mode_name(cmdline.rtcfg_.mode_));
128✔
984
#endif
32✔
985
                }
32✔
986

987
                // Store application defined command line options
988
                rt->set_app_options(params.desc_cmdline);
32✔
989

990
                result = run_or_start(blocking, HPX_MOVE(rt), cmdline,
32✔
991
                    params.startup, params.shutdown);
992
            }
993
            catch (detail::command_line_error const& e)
994
            {
995
                std::cerr << "hpx::init: std::exception caught: " << e.what()
996
                          << "\n";
997
                return -1;
998
            }
999
            return result;
1000
        }
1001

1002
        ////////////////////////////////////////////////////////////////////////
1003
        template <typename T>
1004
        inline T get_option(std::string const& config, T default_ = T())
1005
        {
1006
            if (!config.empty())
1007
            {
1008
                try
1009
                {
1010
                    return hpx::util::from_string<T>(
64✔
1011
                        get_runtime().get_config().get_entry(config, default_));
1012
                }
32✔
1013
                // NOLINTNEXTLINE(bugprone-empty-catch)
×
1014
                catch (hpx::util::bad_lexical_cast const&)
1015
                {
1016
                    // do nothing
×
1017
                }
1018
            }
×
1019
            return default_;
32✔
1020
        }
1021
    }    // namespace detail
1022

1023
    ///////////////////////////////////////////////////////////////////////////
1024
    int finalize(double shutdown_timeout, double localwait, error_code& ec)
58✔
1025
    {
1026
        if (!threads::get_self_ptr())
58✔
1027
        {
1028
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::finalize",
1029
                "this function can be called from an HPX thread only");
1030
            return -1;
116✔
1031
        }
58✔
1032

1033
        if (!is_running())
×
1034
        {
1035
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::finalize",
1036
                "the runtime system is not active (did you already "
1037
                "call finalize?)");
1038
            return -1;
1039
        }
1040

1041
        if (&ec != &throws)
1042
            ec = make_success_code();
1043

29✔
1044
        if (std::abs(localwait + 1.0) < 1e-16)
1045
            localwait = detail::get_option("hpx.finalize_wait_time", -1.0);
29✔
1046

1047
        {
×
1048
            hpx::chrono::high_resolution_timer const t;
1049
            double const start_time = t.elapsed();
×
1050
            double current;
1051
            do
1052
            {
29✔
1053
                current = t.elapsed();
1054
            } while (current - start_time < localwait * 1e-6);
×
1055
        }
1056

1057
        if (std::abs(shutdown_timeout + 1.0) < 1e-16)
×
1058
            shutdown_timeout = detail::get_option("hpx.shutdown_timeout", -1.0);
1059

1060
        runtime* rt = get_runtime_ptr();
29✔
1061
        if (nullptr == rt)
×
1062
        {
1063
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::finalize",
29✔
1064
                "the runtime system is not active (did you already "
58✔
1065
                "call hpx::stop?)");
1066
            return -1;
1067
        }
1068

1069
        rt->finalize(shutdown_timeout);
1070

1071
        // invoke user supplied finalizer
1072
        if (hpx::on_finalize != nullptr)
1073
        {
29✔
1074
            (*hpx::on_finalize)();
1075
        }
1076
        return 0;
29✔
1077
    }
58✔
1078

1079
    ///////////////////////////////////////////////////////////////////////////
29✔
1080
    int disconnect(double shutdown_timeout, double localwait, error_code& ec)
29✔
1081
    {
1082
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
×
1083
        if (!threads::get_self_ptr())
1084
        {
1085
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::disconnect",
×
1086
                "this function can be called from an HPX thread only");
1087
            return -1;
1088
        }
29✔
1089

1090
        if (!is_running())
1091
        {
29✔
1092
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::disconnect",
1093
                "the runtime system is not active (did you already "
×
1094
                "call finalize?)");
1095
            return -1;
1096
        }
1097

1098
        if (&ec != &throws)
1099
            ec = make_success_code();
×
1100

1101
        if (std::abs(localwait + 1.0) < 1e-16)
1102
            localwait = detail::get_option("hpx.finalize_wait_time", -1.0);
×
1103

1104
        {
×
1105
            hpx::chrono::high_resolution_timer const t;
1106
            double const start_time = t.elapsed();
×
1107
            double current;
1108
            do
1109
            {
×
1110
                current = t.elapsed();
1111
            } while (current - start_time < localwait * 1e-6);
×
1112
        }
1113

1114
        if (std::abs(shutdown_timeout + 1.0) < 1e-16)
×
1115
            shutdown_timeout = detail::get_option("hpx.shutdown_timeout", -1.0);
1116

1117
        auto* p = static_cast<components::server::runtime_support*>(
×
1118
            get_runtime_distributed().get_runtime_support_lva());
×
1119

1120
        if (nullptr == p)
×
1121
        {
×
1122
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::disconnect",
1123
                "the runtime system is not active (did you already "
1124
                "call finalize?)");
1125
            return -1;
1126
        }
1127

1128
        p->call_shutdown_functions(true);
1129
        p->call_shutdown_functions(false);
1130

×
1131
        p->stop(shutdown_timeout, hpx::invalid_id, true);
1132
#else
1133
        HPX_UNUSED(shutdown_timeout);
×
1134
        HPX_UNUSED(localwait);
×
1135
        HPX_UNUSED(ec);
1136
#endif
1137

×
1138
        return 0;
1139
    }
×
1140

1141
    ///////////////////////////////////////////////////////////////////////////
×
1142
    void terminate()
1143
    {
1144
        if (!threads::get_self_ptr())
×
1145
        {
1146
            // hpx::terminate shouldn't be called from a non-HPX thread
1147
            std::terminate();
×
1148
        }
×
1149

1150
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
×
1151
        auto* p = static_cast<components::server::runtime_support*>(
1152
            get_runtime_distributed().get_runtime_support_lva());
1153

1154
        if (nullptr == p)
1155
        {
1156
            // the runtime system is not running, just terminate
1157
            std::terminate();
×
1158
        }
1159

1160
        p->terminate_all();
1161
#else
×
1162
        std::terminate();
1163
#endif
×
1164
    }
1165

1166
    ///////////////////////////////////////////////////////////////////////////
×
1167
    int stop(error_code& ec)
1168
    {
1169
        return hpx::local::stop(ec);
1170
    }
1171

×
1172
    ///////////////////////////////////////////////////////////////////////////
1173
    int suspend(error_code& ec)
×
1174
    {
1175
        return hpx::local::suspend(ec);
1176
    }
×
1177

1178
    ///////////////////////////////////////////////////////////////////////////
1179
    int resume(error_code& ec)
×
1180
    {
1181
        return hpx::local::resume(ec);
1182
    }
1183
}    // 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