10ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
20ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// detail/impl/handler_tracking.ipp
30ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
50ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
60ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
70ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Distributed under the Boost Software License, Version 1.0. (See accompanying
80ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
90ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#ifndef ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#define ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/config.hpp"
160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#if defined(ASIO_ENABLE_HANDLER_TRACKING)
180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include <cstdarg>
200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include <cstdio>
210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/handler_tracking.hpp"
220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#  include <chrono>
240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie# include "asio/detail/chrono_time_traits.hpp"
250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie# include "asio/wait_traits.hpp"
260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie# include <unistd.h>
280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/push_options.hpp"
300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace asio {
320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace detail {
330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiestruct handler_tracking_timestamp
350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  uint64_t seconds;
370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  uint64_t microseconds;
380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  handler_tracking_timestamp()
400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    typedef chrono_time_traits<std::chrono::system_clock,
420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        asio::wait_traits<std::chrono::system_clock> > traits_helper;
430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    traits_helper::posix_time_duration now(
440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        std::chrono::system_clock::now().time_since_epoch());
450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    seconds = static_cast<uint64_t>(now.total_seconds());
460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000);
470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie};
490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiestruct handler_tracking::tracking_state
510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static_mutex mutex_;
530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  uint64_t next_id_;
540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  tss_ptr<completion>* current_completion_;
550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie};
560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiehandler_tracking::tracking_state* handler_tracking::get_state()
580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static tracking_state state = { ASIO_STATIC_MUTEX_INIT, 1, 0 };
600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  return &state;
610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::init()
640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static tracking_state* state = get_state();
660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  state->mutex_.init();
680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static_mutex::scoped_lock lock(state->mutex_);
700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  if (state->current_completion_ == 0)
710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    state->current_completion_ = new tss_ptr<completion>;
720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::creation(handler_tracking::tracked_handler* h,
750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    const char* object_type, void* object, const char* op_name)
760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static tracking_state* state = get_state();
780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static_mutex::scoped_lock lock(state->mutex_);
800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  h->id_ = state->next_id_++;
810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  lock.unlock();
820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  handler_tracking_timestamp timestamp;
840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  uint64_t current_id = 0;
860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  if (completion* current_completion = *state->current_completion_)
870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    current_id = current_completion->id_;
880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  write_line(
900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n",
910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      timestamp.seconds, timestamp.microseconds,
920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      current_id, h->id_, object_type, object, op_name);
930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiehandler_tracking::completion::completion(handler_tracking::tracked_handler* h)
960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  : id_(h->id_),
970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    invoked_(false),
980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    next_(*get_state()->current_completion_)
990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  *get_state()->current_completion_ = this;
1010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
1020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiehandler_tracking::completion::~completion()
1040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  if (id_)
1060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    handler_tracking_timestamp timestamp;
1080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_line(
1100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        "@asio|%llu.%06llu|%c%llu|\n",
1110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        timestamp.seconds, timestamp.microseconds,
1120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        invoked_ ? '!' : '~', id_);
1130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  *get_state()->current_completion_ = next_;
1160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
1170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::completion::invocation_begin()
1190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  handler_tracking_timestamp timestamp;
1210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  write_line(
1230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      "@asio|%llu.%06llu|>%llu|\n",
1240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      timestamp.seconds, timestamp.microseconds, id_);
1250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  invoked_ = true;
1270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
1280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::completion::invocation_begin(
1300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    const asio::error_code& ec)
1310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  handler_tracking_timestamp timestamp;
1330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  write_line(
1350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n",
1360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      timestamp.seconds, timestamp.microseconds,
1370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      id_, ec.category().name(), ec.value());
1380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  invoked_ = true;
1400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
1410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::completion::invocation_begin(
1430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    const asio::error_code& ec, std::size_t bytes_transferred)
1440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  handler_tracking_timestamp timestamp;
1460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  write_line(
1480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n",
1490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      timestamp.seconds, timestamp.microseconds,
1500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      id_, ec.category().name(), ec.value(),
1510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      static_cast<uint64_t>(bytes_transferred));
1520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  invoked_ = true;
1540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
1550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::completion::invocation_begin(
1570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    const asio::error_code& ec, int signal_number)
1580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  handler_tracking_timestamp timestamp;
1600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  write_line(
1620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n",
1630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      timestamp.seconds, timestamp.microseconds,
1640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      id_, ec.category().name(), ec.value(), signal_number);
1650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  invoked_ = true;
1670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
1680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::completion::invocation_begin(
1700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    const asio::error_code& ec, const char* arg)
1710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  handler_tracking_timestamp timestamp;
1730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  write_line(
1750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n",
1760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      timestamp.seconds, timestamp.microseconds,
1770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      id_, ec.category().name(), ec.value(), arg);
1780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  invoked_ = true;
1800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
1810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::completion::invocation_end()
1830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  if (id_)
1850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
1860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    handler_tracking_timestamp timestamp;
1870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    write_line(
1890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        "@asio|%llu.%06llu|<%llu|\n",
1900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        timestamp.seconds, timestamp.microseconds, id_);
1910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    id_ = 0;
1930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
1950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::operation(const char* object_type,
1970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    void* object, const char* op_name)
1980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
1990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static tracking_state* state = get_state();
2000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  handler_tracking_timestamp timestamp;
2020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  unsigned long long current_id = 0;
2040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  if (completion* current_completion = *state->current_completion_)
2050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    current_id = current_completion->id_;
2060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  write_line(
2080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n",
2090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      timestamp.seconds, timestamp.microseconds,
2100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      current_id, object_type, object, op_name);
2110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
2120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffievoid handler_tracking::write_line(const char* format, ...)
2140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
2150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  using namespace std; // For sprintf (or equivalent).
2160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  va_list args;
2180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  va_start(args, format);
2190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  char line[256] = "";
2210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#if defined(ASIO_HAS_SECURE_RTL)
2220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  int length = vsprintf_s(line, sizeof(line), format, args);
2230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#else // defined(ASIO_HAS_SECURE_RTL)
2240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  int length = vsprintf(line, format, args);
2250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#endif // defined(ASIO_HAS_SECURE_RTL)
2260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  va_end(args);
2280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ::write(STDERR_FILENO, line, length);
2300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie}
2310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace detail
2330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace asio
2340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/pop_options.hpp"
2360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)
2380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
2390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#endif // ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
240