Esempio n. 1
0
bool
wait_for_client_to_be_ready(
  rcl_client_t * client,
  size_t max_tries,
  int64_t period_ms)
{
  rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
  rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 0, 0, 1, 0, rcl_get_default_allocator());
  if (ret != RCL_RET_OK) {
    fprintf(stderr, "Error in wait set init: %s\n", rcl_get_error_string_safe());
    return false;
  }
  auto wait_set_exit = make_scope_exit([&wait_set]() {
    if (rcl_wait_set_fini(&wait_set) != RCL_RET_OK) {
      fprintf(stderr, "Error in wait set fini: %s\n", rcl_get_error_string_safe());
      throw std::runtime_error("error while waiting for client");
    }
  });
  size_t iteration = 0;
  do {
    ++iteration;
    if (rcl_wait_set_clear_clients(&wait_set) != RCL_RET_OK) {
      fprintf(stderr, "Error in wait_set_clear_clients: %s\n", rcl_get_error_string_safe());
      return false;
    }
    if (rcl_wait_set_add_client(&wait_set, client) != RCL_RET_OK) {
      fprintf(stderr, "Error in wait_set_add_client: %s\n", rcl_get_error_string_safe());
      return false;
    }
    ret = rcl_wait(&wait_set, RCL_MS_TO_NS(period_ms));
    if (ret == RCL_RET_TIMEOUT) {
      continue;
    }
    if (ret != RCL_RET_OK) {
      fprintf(stderr, "Error in wait: %s\n", rcl_get_error_string_safe());
      return false;
    }
    for (size_t i = 0; i < wait_set.size_of_clients; ++i) {
      if (wait_set.clients[i] && wait_set.clients[i] == client) {
        return true;
      }
    }
  } while (iteration < max_tries);
  return false;
}
Esempio n. 2
0
void Registry::Initialize(IAllocator* allocator) {
	s_Allocator = allocator;
	#if PROFI_ALLOCATOR == PROFI_LINEAR_ALLOCATOR
	// allocate the internal allocator (ugh)
	auto internalAllocator = static_cast<InternalAllocator*>(allocator->Allocate(sizeof(InternalAllocator)));
	new(internalAllocator) InternalAllocator(allocator);
	s_InternalAllocator = internalAllocator;
	#else
	s_InternalAllocator = s_Allocator;
	#endif

	auto instance = static_cast<Registry*>(s_InternalAllocator->Allocate(sizeof(Registry)));
	auto ex = make_scope_exit([&] {
		s_InternalAllocator->Deallocate(instance);
		s_Allocator = s_InternalAllocator = nullptr;
	});

	new(instance) Registry(allocator);
	ex.dismiss();

	s_Instance = instance;
}
Esempio n. 3
0
void
wait_for_service_to_be_ready(
  rcl_service_t * service,
  size_t max_tries,
  int64_t period_ms,
  bool & success)
{
  rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
  rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 0, 0, 0, 1, rcl_get_default_allocator());
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  auto wait_set_exit = make_scope_exit([&wait_set]() {
    stop_memory_checking();
    rcl_ret_t ret = rcl_wait_set_fini(&wait_set);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  });
  size_t iteration = 0;
  do {
    ++iteration;
    ret = rcl_wait_set_clear_services(&wait_set);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
    ret = rcl_wait_set_add_service(&wait_set, service);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
    ret = rcl_wait(&wait_set, RCL_MS_TO_NS(period_ms));
    if (ret == RCL_RET_TIMEOUT) {
      continue;
    }
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
    for (size_t i = 0; i < wait_set.size_of_services; ++i) {
      if (wait_set.services[i] && wait_set.services[i] == service) {
        success = true;
        return;
      }
    }
  } while (iteration < max_tries);
  success = false;
}
Esempio n. 4
0
int main(int argc, char ** argv)
{
  int main_ret = 0;
  {
    if (rcl_init(argc, argv, rcl_get_default_allocator()) != RCL_RET_OK) {
      fprintf(stderr, "Error in rcl init: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    rcl_node_t node = rcl_get_zero_initialized_node();
    const char * name = "node_name";
    rcl_node_options_t node_options = rcl_node_get_default_options();
    if (rcl_node_init(&node, name, &node_options) != RCL_RET_OK) {
      fprintf(stderr, "Error in node init: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    auto node_exit = make_scope_exit([&main_ret, &node]() {
      if (rcl_node_fini(&node) != RCL_RET_OK) {
        fprintf(stderr, "Error in node fini: %s\n", rcl_get_error_string_safe());
        main_ret = -1;
      }
    });

    const rosidl_service_type_support_t * ts = ROSIDL_GET_TYPE_SUPPORT(
      example_interfaces, srv, AddTwoInts);
    const char * topic = "add_two_ints";

    rcl_client_t client = rcl_get_zero_initialized_client();
    rcl_client_options_t client_options = rcl_client_get_default_options();
    rcl_ret_t ret = rcl_client_init(&client, &node, ts, topic, &client_options);
    if (ret != RCL_RET_OK) {
      fprintf(stderr, "Error in client init: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    auto client_exit = make_scope_exit([&client, &main_ret, &node]() {
      if (rcl_client_fini(&client, &node)) {
        fprintf(stderr, "Error in client fini: %s\n", rcl_get_error_string_safe());
        main_ret = -1;
      }
    });

    // Initialize a request.
    example_interfaces__srv__AddTwoInts_Request client_request;
    example_interfaces__srv__AddTwoInts_Request__init(&client_request);
    client_request.a = 1;
    client_request.b = 2;
    int64_t sequence_number;

    if (rcl_send_request(&client, &client_request, &sequence_number)) {
      fprintf(stderr, "Error in send request: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    if (sequence_number != 1) {
      fprintf(stderr, "Got invalid sequence number\n");
      return -1;
    }

    example_interfaces__srv__AddTwoInts_Request__fini(&client_request);

    // Initialize the response owned by the client and take the response.
    example_interfaces__srv__AddTwoInts_Response client_response;
    example_interfaces__srv__AddTwoInts_Response__init(&client_response);

    if (!wait_for_client_to_be_ready(&client, 1000, 100)) {
      fprintf(stderr, "Client never became ready\n");
      return -1;
    }
    rmw_request_id_t header;
    if (rcl_take_response(&client, &header, &client_response) != RCL_RET_OK) {
      fprintf(stderr, "Error in send response: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    example_interfaces__srv__AddTwoInts_Response__fini(&client_response);
  }

  return main_ret;
}
Esempio n. 5
0
void
SignalThread::run_(const SignalSet& sigset)
{
    // boost::asio has support for signals via signal_set. It does however not
    // accept a sigset_t and neither can a sigset_t nor a ba::signal_set be inspected.

    int sigfd = signalfd(-1,
                         &sigset.sigset(),
                         SFD_NONBLOCK);
    if (sigfd < 0)
    {
        LOG_ERROR("Failed to create signalfd: " << strerror(errno));
        throw Exception("Failed to create signalfd");
    }

    auto exit(make_scope_exit([&]
                              {
                                  close(sigfd);
                              }));

    std::function<void()> g;

    auto f([&](const bs::error_code& ec,
               std::size_t bytes)
           {
               VERIFY(bytes == 0);

               if (ec)
               {
                   LOG_ERROR("error in signal handler: " <<
                             ec.message());
               }
               else
               {
                   signalfd_siginfo si;
                   ssize_t ret = ::read(sigfd,
                                        &si,
                                        sizeof(si));
                   if (ret < 0)
                   {
                       if (ret != EAGAIN)
                       {
                           ret = errno;
                           LOG_ERROR("failed to read siginfo from signalfd: " <<
                                     strerror(ret) << " (" << ret << ")");
                       }
                       g();
                   }
                   else if (ret != sizeof(si))
                   {
                       LOG_ERROR("read less (" << ret << " ) than expected (" <<
                                 sizeof(si) << ") from signalfd");
                   }
                   else
                   {
                       LOG_INFO("caught signal " << si.ssi_signo);
                       handler_(si.ssi_signo);
                       g();
                   }
               }
           });

    ba::posix::stream_descriptor sigdesc(io_service_,
                                         sigfd);

    g = [&]()
        {
            sigdesc.async_read_some(ba::null_buffers(),
                                    f);
        };

    g();

    bs::error_code ec;
    io_service_.run(ec);

    if (ec)
    {
        LOG_ERROR("error running I/O service of signal thread: " <<
                  ec.message());
    };

    LOG_INFO("exiting signal handler thread");
}
Esempio n. 6
0
int main(int argc, char ** argv)
{
  int main_ret = 0;
  {
    if (rcl_init(argc, argv, rcl_get_default_allocator()) != RCL_RET_OK) {
      fprintf(stderr, "Error in rcl init: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    rcl_node_t node = rcl_get_zero_initialized_node();
    const char * name = "node_name";
    rcl_node_options_t node_options = rcl_node_get_default_options();
    if (rcl_node_init(&node, name, &node_options) != RCL_RET_OK) {
      fprintf(stderr, "Error in node init: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    auto node_exit = make_scope_exit([&main_ret, &node]() {
      if (rcl_node_fini(&node) != RCL_RET_OK) {
        fprintf(stderr, "Error in node fini: %s\n", rcl_get_error_string_safe());
        main_ret = -1;
      }
    });

    const rosidl_service_type_support_t * ts = ROSIDL_GET_TYPE_SUPPORT(
      example_interfaces, srv, AddTwoInts);
    const char * topic = "add_two_ints";

    rcl_service_t service = rcl_get_zero_initialized_service();
    rcl_service_options_t service_options = rcl_service_get_default_options();
    rcl_ret_t ret = rcl_service_init(&service, &node, ts, topic, &service_options);
    if (ret != RCL_RET_OK) {
      fprintf(stderr, "Error in service init: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    auto service_exit = make_scope_exit([&main_ret, &service, &node]() {
      if (rcl_service_fini(&service, &node)) {
        fprintf(stderr, "Error in service fini: %s\n", rcl_get_error_string_safe());
        main_ret = -1;
      }
    });

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

    // Initialize a response.
    example_interfaces__srv__AddTwoInts_Response service_response;
    example_interfaces__srv__AddTwoInts_Response__init(&service_response);
    auto response_exit = make_scope_exit([&service_response]() {
      example_interfaces__srv__AddTwoInts_Response__fini(&service_response);
    });

    // Block until a client request comes in.

    if (!wait_for_service_to_be_ready(&service, 1000, 100)) {
      fprintf(stderr, "Service never became ready\n");
      return -1;
    }

    // Take the pending request.
    example_interfaces__srv__AddTwoInts_Request service_request;
    example_interfaces__srv__AddTwoInts_Request__init(&service_request);
    auto request_exit = make_scope_exit([&service_request]() {
      example_interfaces__srv__AddTwoInts_Request__fini(&service_request);
    });
    rmw_request_id_t header;
    // TODO(jacquelinekay) May have to check for timeout error codes
    if (rcl_take_request(&service, &header, &service_request) != RCL_RET_OK) {
      fprintf(stderr, "Error in take_request: %s\n", rcl_get_error_string_safe());
      return -1;
    }

    // Sum the request and send the response.
    service_response.sum = service_request.a + service_request.b;
    if (rcl_send_response(&service, &header, &service_response) != RCL_RET_OK) {
      fprintf(stderr, "Error in send_response: %s\n", rcl_get_error_string_safe());
      return -1;
    }
    // Our scope exits should take care of fini for everything
  }
  return main_ret;
}
Esempio n. 7
0
/* Basic nominal test of a service.
 */
TEST_F(TestServiceFixture, test_service_nominal) {
  stop_memory_checking();
  rcl_ret_t ret;
  const rosidl_service_type_support_t * ts = ROSIDL_GET_TYPE_SUPPORT(
    example_interfaces, srv, AddTwoInts);
  const char * topic = "add_two_ints";

  rcl_service_t service = rcl_get_zero_initialized_service();
  rcl_service_options_t service_options = rcl_service_get_default_options();
  ret = rcl_service_init(&service, this->node_ptr, ts, topic, &service_options);
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();

  // Check that the service name matches what we assigned.
  EXPECT_EQ(strcmp(rcl_service_get_service_name(&service), topic), 0);
  auto service_exit = make_scope_exit([&service, this]() {
    stop_memory_checking();
    rcl_ret_t ret = rcl_service_fini(&service, this->node_ptr);
    EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  });

  rcl_client_t client = rcl_get_zero_initialized_client();
  rcl_client_options_t client_options = rcl_client_get_default_options();
  ret = rcl_client_init(&client, this->node_ptr, ts, topic, &client_options);
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  auto client_exit = make_scope_exit([&client, this]() {
    stop_memory_checking();
    rcl_ret_t ret = rcl_client_fini(&client, this->node_ptr);
    EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  });


  // TODO(wjwwood): add logic to wait for the connection to be established
  //                use count_services busy wait mechanism
  //                until then we will sleep for a short period of time
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));

  // Initialize a request.
  example_interfaces__srv__AddTwoInts_Request client_request;
  example_interfaces__srv__AddTwoInts_Request__init(&client_request);
  client_request.a = 1;
  client_request.b = 2;
  int64_t sequence_number;
  ret = rcl_send_request(&client, &client_request, &sequence_number);
  EXPECT_EQ(sequence_number, 1);
  example_interfaces__srv__AddTwoInts_Request__fini(&client_request);
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();

  bool success;
  wait_for_service_to_be_ready(&service, 10, 100, success);
  ASSERT_TRUE(success);

  // This scope simulates the service responding in a different context so that we can
  // test take_request/send_response in a single-threaded, deterministic execution.
  {
    // Initialize a response.
    example_interfaces__srv__AddTwoInts_Response service_response;
    example_interfaces__srv__AddTwoInts_Response__init(&service_response);
    auto msg_exit = make_scope_exit([&service_response]() {
      stop_memory_checking();
      example_interfaces__srv__AddTwoInts_Response__fini(&service_response);
    });

    // Initialize a separate instance of the request and take the pending request.
    example_interfaces__srv__AddTwoInts_Request service_request;
    example_interfaces__srv__AddTwoInts_Request__init(&service_request);
    rmw_request_id_t header;
    ret = rcl_take_request(&service, &header, &service_request);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();

    EXPECT_EQ(1, service_request.a);
    EXPECT_EQ(2, service_request.b);
    // Simulate a response callback by summing the request and send the response..
    service_response.sum = service_request.a + service_request.b;
    ret = rcl_send_response(&service, &header, &service_response);
    ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  }
  wait_for_service_to_be_ready(&service, 10, 100, success);

  // Initialize the response owned by the client and take the response.
  example_interfaces__srv__AddTwoInts_Response client_response;
  example_interfaces__srv__AddTwoInts_Response__init(&client_response);

  rmw_request_id_t header;
  ret = rcl_take_response(&client, &header, &client_response);
  ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
  EXPECT_EQ(client_response.sum, 3);
  EXPECT_EQ(header.sequence_number, 1);
}