Skip to content

Commit

Permalink
Avoiding more stack overflows
Browse files Browse the repository at this point in the history
This patch makes sure that action invocations always have at least as much
stack space available as they requested.
  • Loading branch information
Thomas Heller committed Feb 7, 2018
1 parent 3d86300 commit d073b08
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 31 deletions.
7 changes: 5 additions & 2 deletions hpx/lcos/detail/async_implementations.hpp
Expand Up @@ -157,10 +157,13 @@ namespace hpx { namespace detail
template <typename Action>
bool can_invoke_locally()
{
return !traits::action_decorate_function<Action>::value &&
this_thread::get_stack_size() >= threads::get_stack_size(
std::ptrdiff_t requested_stack_size =
threads::get_stack_size(
static_cast<threads::thread_stacksize>(
traits::action_stacksize<Action>::value));
return !traits::action_decorate_function<Action>::value &&
this_thread::get_stack_size() >= requested_stack_size &&
this_thread::has_sufficient_stack_space(requested_stack_size);
}

template <typename Action>
Expand Down
57 changes: 28 additions & 29 deletions tests/unit/threads/thread_stacksize.cpp
Expand Up @@ -3,6 +3,8 @@
// 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)

//#define HPX_THREADS_STACK_OVERHEAD 0x5000

#include <hpx/hpx_main.hpp>
#include <hpx/include/actions.hpp>
#include <hpx/include/runtime.hpp>
Expand All @@ -15,19 +17,19 @@
///////////////////////////////////////////////////////////////////////////////
void test_small_stacksize()
{
HPX_TEST(hpx::threads::get_self_ptr());

// verify that sufficient stack has been allocated
HPX_TEST(hpx::threads::get_ctx_ptr()->get_stacksize() >=
hpx::get_runtime().get_config().get_stack_size(
hpx::threads::thread_stacksize_small));

// allocate HPX_SMALL_STACK_SIZE - HPX_THREADS_STACK_OVERHEAD memory on
// the stack
char array[HPX_SMALL_STACK_SIZE-HPX_THREADS_STACK_OVERHEAD];

// do something to that array
std::memset(array, '\0', sizeof(array));

HPX_TEST(hpx::threads::get_self_ptr());

// verify that sufficient stack has been allocated
HPX_TEST(hpx::threads::get_ctx_ptr()->get_stacksize() >=
hpx::get_runtime().get_config().get_stack_size(
hpx::threads::thread_stacksize_small));
}
HPX_DECLARE_ACTION(test_small_stacksize, test_small_stacksize_action)
HPX_ACTION_USES_SMALL_STACK(test_small_stacksize_action)
Expand All @@ -36,19 +38,18 @@ HPX_PLAIN_ACTION(test_small_stacksize, test_small_stacksize_action)
///////////////////////////////////////////////////////////////////////////////
void test_medium_stacksize()
{
// allocate HPX_MEDIUM_STACK_SIZE - HPX_THREADS_STACK_OVERHEAD memory on
// the stack
char array[HPX_MEDIUM_STACK_SIZE-HPX_THREADS_STACK_OVERHEAD];
// do something to that array
std::memset(array, '\0', sizeof(array));

HPX_TEST(hpx::threads::get_self_ptr());

// verify that sufficient stack has been allocated
HPX_TEST(hpx::threads::get_ctx_ptr()->get_stacksize() >=
hpx::get_runtime().get_config().get_stack_size(
hpx::threads::thread_stacksize_medium));

// allocate HPX_MEDIUM_STACK_SIZE - HPX_THREADS_STACK_OVERHEAD memory on
// the stack
char array[HPX_MEDIUM_STACK_SIZE-HPX_THREADS_STACK_OVERHEAD];

// do something to that array
std::memset(array, '\0', sizeof(array));
}
HPX_DECLARE_ACTION(test_medium_stacksize, test_medium_stacksize_action)
HPX_ACTION_USES_MEDIUM_STACK(test_medium_stacksize_action)
Expand All @@ -57,19 +58,18 @@ HPX_PLAIN_ACTION(test_medium_stacksize, test_medium_stacksize_action)
///////////////////////////////////////////////////////////////////////////////
void test_large_stacksize()
{
// allocate HPX_LARGE_STACK_SIZE - HPX_THREADS_STACK_OVERHEAD memory on
// the stack
char array[HPX_LARGE_STACK_SIZE-HPX_THREADS_STACK_OVERHEAD];
// do something to that array
std::memset(array, '\0', sizeof(array));

HPX_TEST(hpx::threads::get_self_ptr());

// verify that sufficient stack has been allocated
HPX_TEST(hpx::threads::get_ctx_ptr()->get_stacksize() >=
hpx::get_runtime().get_config().get_stack_size(
hpx::threads::thread_stacksize_large));

// allocate HPX_LARGE_STACK_SIZE - HPX_THREADS_STACK_OVERHEAD memory on
// the stack
char array[HPX_LARGE_STACK_SIZE-HPX_THREADS_STACK_OVERHEAD];

// do something to that array
std::memset(array, '\0', sizeof(array));
}
HPX_DECLARE_ACTION(test_large_stacksize, test_large_stacksize_action)
HPX_ACTION_USES_LARGE_STACK(test_large_stacksize_action)
Expand All @@ -78,19 +78,19 @@ HPX_PLAIN_ACTION(test_large_stacksize, test_large_stacksize_action)
///////////////////////////////////////////////////////////////////////////////
void test_huge_stacksize()
{
HPX_TEST(hpx::threads::get_self_ptr());

// verify that sufficient stack has been allocated
HPX_TEST(hpx::threads::get_ctx_ptr()->get_stacksize() >=
hpx::get_runtime().get_config().get_stack_size(
hpx::threads::thread_stacksize_huge));

// allocate HPX_LARGE_STACK_SIZE - HPX_THREADS_STACK_OVERHEAD memory on
// the stack
char array[HPX_HUGE_STACK_SIZE-HPX_THREADS_STACK_OVERHEAD];

// do something to that array
std::memset(array, '\0', sizeof(array));

HPX_TEST(hpx::threads::get_self_ptr());

// verify that sufficient stack has been allocated
HPX_TEST(hpx::threads::get_ctx_ptr()->get_stacksize() >=
hpx::get_runtime().get_config().get_stack_size(
hpx::threads::thread_stacksize_huge));
}
HPX_DECLARE_ACTION(test_huge_stacksize, test_huge_stacksize_action)
HPX_ACTION_USES_HUGE_STACK(test_huge_stacksize_action)
Expand All @@ -103,7 +103,6 @@ int main()

for (hpx::id_type const& id : localities)
{
if (id != hpx::find_here())
{
test_small_stacksize_action test_action;
test_action(id);
Expand Down

0 comments on commit d073b08

Please sign in to comment.