diff --git a/hpx/runtime/agas/addressing_service.hpp b/hpx/runtime/agas/addressing_service.hpp index f9b714adaf49..9f4ebeff9d07 100644 --- a/hpx/runtime/agas/addressing_service.hpp +++ b/hpx/runtime/agas/addressing_service.hpp @@ -324,6 +324,10 @@ struct HPX_EXPORT addressing_service : boost::noncopyable , error_code& ec = throws ); + bool has_resolved_locality( + naming::gid_type const & gid + ); + /// \brief Remove a locality from the runtime. bool unregister_locality( naming::gid_type const & gid diff --git a/src/runtime/agas/addressing_service.cpp b/src/runtime/agas/addressing_service.cpp index 2dbdb064b4c9..48be8f1dbf72 100644 --- a/src/runtime/agas/addressing_service.cpp +++ b/src/runtime/agas/addressing_service.cpp @@ -538,6 +538,14 @@ void addressing_service::register_console(parcelset::endpoints_type const & eps) HPX_ASSERT(res.second); } +bool addressing_service::has_resolved_locality( + naming::gid_type const & gid + ) +{ // {{{ + boost::unique_lock l(resolved_localities_mtx_); + return resolved_localities_.find(gid) != resolved_localities_.end(); +} // }}} + parcelset::endpoints_type const & addressing_service::resolve_locality( naming::gid_type const & gid , error_code& ec @@ -578,9 +586,7 @@ parcelset::endpoints_type const & addressing_service::resolve_locality( if (0 == threads::get_self_ptr()) { // this should happen only during bootstrap - // FIXME: Disabled this assert cause it fires. - // It should not, but doesn't do any harm - //HPX_ASSERT(hpx::is_starting()); + HPX_ASSERT(hpx::is_starting()); while(!endpoints_future.is_ready()) /**/; diff --git a/src/runtime/parcelset/parcelhandler.cpp b/src/runtime/parcelset/parcelhandler.cpp index cf9c195c3046..c85783b825b5 100644 --- a/src/runtime/parcelset/parcelhandler.cpp +++ b/src/runtime/parcelset/parcelhandler.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -365,12 +366,36 @@ namespace hpx { namespace parcelset { HPX_ASSERT(resolver_); - // properly initialize parcel - init_parcel(p); - naming::id_type const* ids = p.destinations(); naming::address* addrs = p.addrs(); + // During bootstrap this is handled separately (see + // addressing_service::resolve_locality. + if (0 == hpx::threads::get_self_ptr() && !hpx::is_starting()) + { + HPX_ASSERT(resolver_); + naming::gid_type locality = + naming::get_locality_from_gid(ids[0].get_gid()); + if (!resolver_->has_resolved_locality(locality)) + { + // reschedule request as an HPX thread to avoid hangs + void (parcelhandler::*put_parcel_ptr) ( + parcel p, write_handler_type f + ) = &parcelhandler::put_parcel; + + threads::register_thread_nullary( + util::bind( + util::one_shot(put_parcel_ptr), this, + std::move(p), std::move(f)), + "parcelhandler::put_parcel", threads::pending, true, + threads::thread_priority_boost); + return; + } + } + + // properly initialize parcel + init_parcel(p); + bool resolved_locally = true; #if !defined(HPX_SUPPORT_MULTIPLE_PARCEL_DESTINATIONS) diff --git a/tests/regressions/agas/CMakeLists.txt b/tests/regressions/agas/CMakeLists.txt index fc15bdc2d207..686981662f87 100644 --- a/tests/regressions/agas/CMakeLists.txt +++ b/tests/regressions/agas/CMakeLists.txt @@ -8,8 +8,11 @@ set(tests duplicate_id_registration_1596 pass_by_value_id_type_action send_gid_keep_component_1624 + register_with_basename_1804 ) +set(register_with_basename_1804_PARAMETERS LOCALITIES 4) + foreach(test ${tests}) set(sources ${test}.cpp) diff --git a/tests/regressions/agas/register_with_basename_1804.cpp b/tests/regressions/agas/register_with_basename_1804.cpp new file mode 100644 index 000000000000..bcfcd125f9bd --- /dev/null +++ b/tests/regressions/agas/register_with_basename_1804.cpp @@ -0,0 +1,103 @@ +// Copyright (c) 2015 Andreas Schaefer +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// This illustrates the issue as reported by #1804: register_with_basename +// causes hangs + +#include +#include +#include + +#include +#include + +#include + +static std::string itoa(int i) +{ + std::stringstream buf; + buf << i; + return buf.str(); +} + +struct test_server + : hpx::components::simple_component_base +{ + test_server() + {} + + hpx::id_type call() const + { + return hpx::find_here(); + } + HPX_DEFINE_COMPONENT_ACTION(test_server, call, call_action); +}; + +typedef hpx::components::simple_component server_type; +HPX_REGISTER_COMPONENT(server_type, test_server); + +typedef test_server::call_action call_action; +HPX_REGISTER_ACTION(call_action); + +std::string gen_name(int source, int target) +{ + std::string basename = "/0/HPXSimulatorUpdateGroupSdfafafasdasd"; + + return basename + "/PatchLink/" + + itoa(source) + "-" + + itoa(target); +} + +void test() +{ + int rank = hpx::get_locality_id(); + + std::vector boundingBoxReceivers; + std::vector boundingBoxAccepters; + for (int i = 0; i < 4; ++i) { + if (i == rank) + continue; + + std::string name = gen_name(i, rank); + std::cout << "registration: " << name << "\n"; + + hpx::id_type id = hpx::new_(hpx::find_here()).get(); + hpx::register_with_basename(name, id, 0).get(); + boundingBoxReceivers.push_back(id); + } + + for (int i = 0; i < 4; ++i) { + if (i == rank) + continue; + + std::string name = gen_name(rank, i); + std::cout << "lookup: " << name << "\n"; + std::vector > ids = + hpx::find_all_from_basename(name, 1); + boundingBoxAccepters.push_back(std::move(ids[0].get())); + } + + std::cout << "all done " << rank << "\n"; +} + +int hpx_main(int argc, char **argv) +{ + // this test must run using 4 localities + HPX_TEST_EQ(hpx::get_num_localities().get(), 4u); + + test(); + return hpx::finalize(); +} + +int main(int argc, char **argv) +{ + // We want HPX to run hpx_main() on all localities to avoid the + // initial overhead caused by broadcasting the work from one to + // all other localities: + std::vector config(1, "hpx.run_hpx_main!=1"); + + HPX_TEST_EQ(hpx::init(argc, argv, config), 0); + return hpx::util::report_errors(); +}