signal_set_service.ipp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. //
  2. // detail/impl/signal_set_service.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  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. #ifndef BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP
  11. #define BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <cstring>
  17. #include <boost/asio/detail/reactor.hpp>
  18. #include <boost/asio/detail/signal_blocker.hpp>
  19. #include <boost/asio/detail/signal_set_service.hpp>
  20. #include <boost/asio/detail/static_mutex.hpp>
  21. #include <boost/asio/detail/push_options.hpp>
  22. namespace boost {
  23. namespace asio {
  24. namespace detail {
  25. struct signal_state
  26. {
  27. // Mutex used for protecting global state.
  28. static_mutex mutex_;
  29. // The read end of the pipe used for signal notifications.
  30. int read_descriptor_;
  31. // The write end of the pipe used for signal notifications.
  32. int write_descriptor_;
  33. // Whether the signal state has been prepared for a fork.
  34. bool fork_prepared_;
  35. // The head of a linked list of all signal_set_service instances.
  36. class signal_set_service* service_list_;
  37. // A count of the number of objects that are registered for each signal.
  38. std::size_t registration_count_[max_signal_number];
  39. };
  40. signal_state* get_signal_state()
  41. {
  42. static signal_state state = {
  43. BOOST_ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, { 0 } };
  44. return &state;
  45. }
  46. void boost_asio_signal_handler(int signal_number)
  47. {
  48. #if defined(BOOST_ASIO_WINDOWS) \
  49. || defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  50. || defined(__CYGWIN__)
  51. signal_set_service::deliver_signal(signal_number);
  52. #else // defined(BOOST_ASIO_WINDOWS)
  53. // || defined(BOOST_ASIO_WINDOWS_RUNTIME)
  54. // || defined(__CYGWIN__)
  55. int saved_errno = errno;
  56. signal_state* state = get_signal_state();
  57. signed_size_type result = ::write(state->write_descriptor_,
  58. &signal_number, sizeof(signal_number));
  59. (void)result;
  60. errno = saved_errno;
  61. #endif // defined(BOOST_ASIO_WINDOWS)
  62. // || defined(BOOST_ASIO_WINDOWS_RUNTIME)
  63. // || defined(__CYGWIN__)
  64. #if defined(BOOST_ASIO_HAS_SIGNAL) && !defined(BOOST_ASIO_HAS_SIGACTION)
  65. ::signal(signal_number, boost_asio_signal_handler);
  66. #endif // defined(BOOST_ASIO_HAS_SIGNAL) && !defined(BOOST_ASIO_HAS_SIGACTION)
  67. }
  68. #if !defined(BOOST_ASIO_WINDOWS) \
  69. && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  70. && !defined(__CYGWIN__)
  71. class signal_set_service::pipe_read_op : public reactor_op
  72. {
  73. public:
  74. pipe_read_op()
  75. : reactor_op(&pipe_read_op::do_perform, pipe_read_op::do_complete)
  76. {
  77. }
  78. static bool do_perform(reactor_op*)
  79. {
  80. signal_state* state = get_signal_state();
  81. int fd = state->read_descriptor_;
  82. int signal_number = 0;
  83. while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))
  84. if (signal_number >= 0 && signal_number < max_signal_number)
  85. signal_set_service::deliver_signal(signal_number);
  86. return false;
  87. }
  88. static void do_complete(io_service_impl* /*owner*/, operation* base,
  89. const boost::system::error_code& /*ec*/,
  90. std::size_t /*bytes_transferred*/)
  91. {
  92. pipe_read_op* o(static_cast<pipe_read_op*>(base));
  93. delete o;
  94. }
  95. };
  96. #endif // !defined(BOOST_ASIO_WINDOWS)
  97. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  98. // && !defined(__CYGWIN__)
  99. signal_set_service::signal_set_service(
  100. boost::asio::io_service& io_service)
  101. : io_service_(boost::asio::use_service<io_service_impl>(io_service)),
  102. #if !defined(BOOST_ASIO_WINDOWS) \
  103. && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  104. && !defined(__CYGWIN__)
  105. reactor_(boost::asio::use_service<reactor>(io_service)),
  106. #endif // !defined(BOOST_ASIO_WINDOWS)
  107. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  108. // && !defined(__CYGWIN__)
  109. next_(0),
  110. prev_(0)
  111. {
  112. get_signal_state()->mutex_.init();
  113. #if !defined(BOOST_ASIO_WINDOWS) \
  114. && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  115. && !defined(__CYGWIN__)
  116. reactor_.init_task();
  117. #endif // !defined(BOOST_ASIO_WINDOWS)
  118. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  119. // && !defined(__CYGWIN__)
  120. for (int i = 0; i < max_signal_number; ++i)
  121. registrations_[i] = 0;
  122. add_service(this);
  123. }
  124. signal_set_service::~signal_set_service()
  125. {
  126. remove_service(this);
  127. }
  128. void signal_set_service::shutdown_service()
  129. {
  130. remove_service(this);
  131. op_queue<operation> ops;
  132. for (int i = 0; i < max_signal_number; ++i)
  133. {
  134. registration* reg = registrations_[i];
  135. while (reg)
  136. {
  137. ops.push(*reg->queue_);
  138. reg = reg->next_in_table_;
  139. }
  140. }
  141. io_service_.abandon_operations(ops);
  142. }
  143. void signal_set_service::fork_service(
  144. boost::asio::io_service::fork_event fork_ev)
  145. {
  146. #if !defined(BOOST_ASIO_WINDOWS) \
  147. && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  148. && !defined(__CYGWIN__)
  149. signal_state* state = get_signal_state();
  150. static_mutex::scoped_lock lock(state->mutex_);
  151. switch (fork_ev)
  152. {
  153. case boost::asio::io_service::fork_prepare:
  154. {
  155. int read_descriptor = state->read_descriptor_;
  156. state->fork_prepared_ = true;
  157. lock.unlock();
  158. reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_);
  159. }
  160. break;
  161. case boost::asio::io_service::fork_parent:
  162. if (state->fork_prepared_)
  163. {
  164. int read_descriptor = state->read_descriptor_;
  165. state->fork_prepared_ = false;
  166. lock.unlock();
  167. reactor_.register_internal_descriptor(reactor::read_op,
  168. read_descriptor, reactor_data_, new pipe_read_op);
  169. }
  170. break;
  171. case boost::asio::io_service::fork_child:
  172. if (state->fork_prepared_)
  173. {
  174. boost::asio::detail::signal_blocker blocker;
  175. close_descriptors();
  176. open_descriptors();
  177. int read_descriptor = state->read_descriptor_;
  178. state->fork_prepared_ = false;
  179. lock.unlock();
  180. reactor_.register_internal_descriptor(reactor::read_op,
  181. read_descriptor, reactor_data_, new pipe_read_op);
  182. }
  183. break;
  184. default:
  185. break;
  186. }
  187. #else // !defined(BOOST_ASIO_WINDOWS)
  188. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  189. // && !defined(__CYGWIN__)
  190. (void)fork_ev;
  191. #endif // !defined(BOOST_ASIO_WINDOWS)
  192. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  193. // && !defined(__CYGWIN__)
  194. }
  195. void signal_set_service::construct(
  196. signal_set_service::implementation_type& impl)
  197. {
  198. impl.signals_ = 0;
  199. }
  200. void signal_set_service::destroy(
  201. signal_set_service::implementation_type& impl)
  202. {
  203. boost::system::error_code ignored_ec;
  204. clear(impl, ignored_ec);
  205. cancel(impl, ignored_ec);
  206. }
  207. boost::system::error_code signal_set_service::add(
  208. signal_set_service::implementation_type& impl,
  209. int signal_number, boost::system::error_code& ec)
  210. {
  211. // Check that the signal number is valid.
  212. if (signal_number < 0 || signal_number > max_signal_number)
  213. {
  214. ec = boost::asio::error::invalid_argument;
  215. return ec;
  216. }
  217. signal_state* state = get_signal_state();
  218. static_mutex::scoped_lock lock(state->mutex_);
  219. // Find the appropriate place to insert the registration.
  220. registration** insertion_point = &impl.signals_;
  221. registration* next = impl.signals_;
  222. while (next && next->signal_number_ < signal_number)
  223. {
  224. insertion_point = &next->next_in_set_;
  225. next = next->next_in_set_;
  226. }
  227. // Only do something if the signal is not already registered.
  228. if (next == 0 || next->signal_number_ != signal_number)
  229. {
  230. registration* new_registration = new registration;
  231. #if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
  232. // Register for the signal if we're the first.
  233. if (state->registration_count_[signal_number] == 0)
  234. {
  235. # if defined(BOOST_ASIO_HAS_SIGACTION)
  236. using namespace std; // For memset.
  237. struct sigaction sa;
  238. memset(&sa, 0, sizeof(sa));
  239. sa.sa_handler = boost_asio_signal_handler;
  240. sigfillset(&sa.sa_mask);
  241. if (::sigaction(signal_number, &sa, 0) == -1)
  242. # else // defined(BOOST_ASIO_HAS_SIGACTION)
  243. if (::signal(signal_number, boost_asio_signal_handler) == SIG_ERR)
  244. # endif // defined(BOOST_ASIO_HAS_SIGACTION)
  245. {
  246. # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  247. ec = boost::asio::error::invalid_argument;
  248. # else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  249. ec = boost::system::error_code(errno,
  250. boost::asio::error::get_system_category());
  251. # endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  252. delete new_registration;
  253. return ec;
  254. }
  255. }
  256. #endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
  257. // Record the new registration in the set.
  258. new_registration->signal_number_ = signal_number;
  259. new_registration->queue_ = &impl.queue_;
  260. new_registration->next_in_set_ = next;
  261. *insertion_point = new_registration;
  262. // Insert registration into the registration table.
  263. new_registration->next_in_table_ = registrations_[signal_number];
  264. if (registrations_[signal_number])
  265. registrations_[signal_number]->prev_in_table_ = new_registration;
  266. registrations_[signal_number] = new_registration;
  267. ++state->registration_count_[signal_number];
  268. }
  269. ec = boost::system::error_code();
  270. return ec;
  271. }
  272. boost::system::error_code signal_set_service::remove(
  273. signal_set_service::implementation_type& impl,
  274. int signal_number, boost::system::error_code& ec)
  275. {
  276. // Check that the signal number is valid.
  277. if (signal_number < 0 || signal_number > max_signal_number)
  278. {
  279. ec = boost::asio::error::invalid_argument;
  280. return ec;
  281. }
  282. signal_state* state = get_signal_state();
  283. static_mutex::scoped_lock lock(state->mutex_);
  284. // Find the signal number in the list of registrations.
  285. registration** deletion_point = &impl.signals_;
  286. registration* reg = impl.signals_;
  287. while (reg && reg->signal_number_ < signal_number)
  288. {
  289. deletion_point = &reg->next_in_set_;
  290. reg = reg->next_in_set_;
  291. }
  292. if (reg != 0 && reg->signal_number_ == signal_number)
  293. {
  294. #if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
  295. // Set signal handler back to the default if we're the last.
  296. if (state->registration_count_[signal_number] == 1)
  297. {
  298. # if defined(BOOST_ASIO_HAS_SIGACTION)
  299. using namespace std; // For memset.
  300. struct sigaction sa;
  301. memset(&sa, 0, sizeof(sa));
  302. sa.sa_handler = SIG_DFL;
  303. if (::sigaction(signal_number, &sa, 0) == -1)
  304. # else // defined(BOOST_ASIO_HAS_SIGACTION)
  305. if (::signal(signal_number, SIG_DFL) == SIG_ERR)
  306. # endif // defined(BOOST_ASIO_HAS_SIGACTION)
  307. {
  308. # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  309. ec = boost::asio::error::invalid_argument;
  310. # else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  311. ec = boost::system::error_code(errno,
  312. boost::asio::error::get_system_category());
  313. # endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  314. return ec;
  315. }
  316. }
  317. #endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
  318. // Remove the registration from the set.
  319. *deletion_point = reg->next_in_set_;
  320. // Remove the registration from the registration table.
  321. if (registrations_[signal_number] == reg)
  322. registrations_[signal_number] = reg->next_in_table_;
  323. if (reg->prev_in_table_)
  324. reg->prev_in_table_->next_in_table_ = reg->next_in_table_;
  325. if (reg->next_in_table_)
  326. reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;
  327. --state->registration_count_[signal_number];
  328. delete reg;
  329. }
  330. ec = boost::system::error_code();
  331. return ec;
  332. }
  333. boost::system::error_code signal_set_service::clear(
  334. signal_set_service::implementation_type& impl,
  335. boost::system::error_code& ec)
  336. {
  337. signal_state* state = get_signal_state();
  338. static_mutex::scoped_lock lock(state->mutex_);
  339. while (registration* reg = impl.signals_)
  340. {
  341. #if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
  342. // Set signal handler back to the default if we're the last.
  343. if (state->registration_count_[reg->signal_number_] == 1)
  344. {
  345. # if defined(BOOST_ASIO_HAS_SIGACTION)
  346. using namespace std; // For memset.
  347. struct sigaction sa;
  348. memset(&sa, 0, sizeof(sa));
  349. sa.sa_handler = SIG_DFL;
  350. if (::sigaction(reg->signal_number_, &sa, 0) == -1)
  351. # else // defined(BOOST_ASIO_HAS_SIGACTION)
  352. if (::signal(reg->signal_number_, SIG_DFL) == SIG_ERR)
  353. # endif // defined(BOOST_ASIO_HAS_SIGACTION)
  354. {
  355. # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  356. ec = boost::asio::error::invalid_argument;
  357. # else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  358. ec = boost::system::error_code(errno,
  359. boost::asio::error::get_system_category());
  360. # endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  361. return ec;
  362. }
  363. }
  364. #endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
  365. // Remove the registration from the registration table.
  366. if (registrations_[reg->signal_number_] == reg)
  367. registrations_[reg->signal_number_] = reg->next_in_table_;
  368. if (reg->prev_in_table_)
  369. reg->prev_in_table_->next_in_table_ = reg->next_in_table_;
  370. if (reg->next_in_table_)
  371. reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;
  372. --state->registration_count_[reg->signal_number_];
  373. impl.signals_ = reg->next_in_set_;
  374. delete reg;
  375. }
  376. ec = boost::system::error_code();
  377. return ec;
  378. }
  379. boost::system::error_code signal_set_service::cancel(
  380. signal_set_service::implementation_type& impl,
  381. boost::system::error_code& ec)
  382. {
  383. BOOST_ASIO_HANDLER_OPERATION(("signal_set", &impl, "cancel"));
  384. op_queue<operation> ops;
  385. {
  386. signal_state* state = get_signal_state();
  387. static_mutex::scoped_lock lock(state->mutex_);
  388. while (signal_op* op = impl.queue_.front())
  389. {
  390. op->ec_ = boost::asio::error::operation_aborted;
  391. impl.queue_.pop();
  392. ops.push(op);
  393. }
  394. }
  395. io_service_.post_deferred_completions(ops);
  396. ec = boost::system::error_code();
  397. return ec;
  398. }
  399. void signal_set_service::deliver_signal(int signal_number)
  400. {
  401. signal_state* state = get_signal_state();
  402. static_mutex::scoped_lock lock(state->mutex_);
  403. signal_set_service* service = state->service_list_;
  404. while (service)
  405. {
  406. op_queue<operation> ops;
  407. registration* reg = service->registrations_[signal_number];
  408. while (reg)
  409. {
  410. if (reg->queue_->empty())
  411. {
  412. ++reg->undelivered_;
  413. }
  414. else
  415. {
  416. while (signal_op* op = reg->queue_->front())
  417. {
  418. op->signal_number_ = signal_number;
  419. reg->queue_->pop();
  420. ops.push(op);
  421. }
  422. }
  423. reg = reg->next_in_table_;
  424. }
  425. service->io_service_.post_deferred_completions(ops);
  426. service = service->next_;
  427. }
  428. }
  429. void signal_set_service::add_service(signal_set_service* service)
  430. {
  431. signal_state* state = get_signal_state();
  432. static_mutex::scoped_lock lock(state->mutex_);
  433. #if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
  434. // If this is the first service to be created, open a new pipe.
  435. if (state->service_list_ == 0)
  436. open_descriptors();
  437. #endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
  438. // Insert service into linked list of all services.
  439. service->next_ = state->service_list_;
  440. service->prev_ = 0;
  441. if (state->service_list_)
  442. state->service_list_->prev_ = service;
  443. state->service_list_ = service;
  444. #if !defined(BOOST_ASIO_WINDOWS) \
  445. && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  446. && !defined(__CYGWIN__)
  447. // Register for pipe readiness notifications.
  448. int read_descriptor = state->read_descriptor_;
  449. lock.unlock();
  450. service->reactor_.register_internal_descriptor(reactor::read_op,
  451. read_descriptor, service->reactor_data_, new pipe_read_op);
  452. #endif // !defined(BOOST_ASIO_WINDOWS)
  453. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  454. // && !defined(__CYGWIN__)
  455. }
  456. void signal_set_service::remove_service(signal_set_service* service)
  457. {
  458. signal_state* state = get_signal_state();
  459. static_mutex::scoped_lock lock(state->mutex_);
  460. if (service->next_ || service->prev_ || state->service_list_ == service)
  461. {
  462. #if !defined(BOOST_ASIO_WINDOWS) \
  463. && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  464. && !defined(__CYGWIN__)
  465. // Disable the pipe readiness notifications.
  466. int read_descriptor = state->read_descriptor_;
  467. lock.unlock();
  468. service->reactor_.deregister_descriptor(
  469. read_descriptor, service->reactor_data_, false);
  470. lock.lock();
  471. #endif // !defined(BOOST_ASIO_WINDOWS)
  472. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  473. // && !defined(__CYGWIN__)
  474. // Remove service from linked list of all services.
  475. if (state->service_list_ == service)
  476. state->service_list_ = service->next_;
  477. if (service->prev_)
  478. service->prev_->next_ = service->next_;
  479. if (service->next_)
  480. service->next_->prev_= service->prev_;
  481. service->next_ = 0;
  482. service->prev_ = 0;
  483. #if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
  484. // If this is the last service to be removed, close the pipe.
  485. if (state->service_list_ == 0)
  486. close_descriptors();
  487. #endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
  488. }
  489. }
  490. void signal_set_service::open_descriptors()
  491. {
  492. #if !defined(BOOST_ASIO_WINDOWS) \
  493. && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  494. && !defined(__CYGWIN__)
  495. signal_state* state = get_signal_state();
  496. int pipe_fds[2];
  497. if (::pipe(pipe_fds) == 0)
  498. {
  499. state->read_descriptor_ = pipe_fds[0];
  500. ::fcntl(state->read_descriptor_, F_SETFL, O_NONBLOCK);
  501. state->write_descriptor_ = pipe_fds[1];
  502. ::fcntl(state->write_descriptor_, F_SETFL, O_NONBLOCK);
  503. #if defined(FD_CLOEXEC)
  504. ::fcntl(state->read_descriptor_, F_SETFD, FD_CLOEXEC);
  505. ::fcntl(state->write_descriptor_, F_SETFD, FD_CLOEXEC);
  506. #endif // defined(FD_CLOEXEC)
  507. }
  508. else
  509. {
  510. boost::system::error_code ec(errno,
  511. boost::asio::error::get_system_category());
  512. boost::asio::detail::throw_error(ec, "signal_set_service pipe");
  513. }
  514. #endif // !defined(BOOST_ASIO_WINDOWS)
  515. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  516. // && !defined(__CYGWIN__)
  517. }
  518. void signal_set_service::close_descriptors()
  519. {
  520. #if !defined(BOOST_ASIO_WINDOWS) \
  521. && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
  522. && !defined(__CYGWIN__)
  523. signal_state* state = get_signal_state();
  524. if (state->read_descriptor_ != -1)
  525. ::close(state->read_descriptor_);
  526. state->read_descriptor_ = -1;
  527. if (state->write_descriptor_ != -1)
  528. ::close(state->write_descriptor_);
  529. state->write_descriptor_ = -1;
  530. #endif // !defined(BOOST_ASIO_WINDOWS)
  531. // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
  532. // && !defined(__CYGWIN__)
  533. }
  534. void signal_set_service::start_wait_op(
  535. signal_set_service::implementation_type& impl, signal_op* op)
  536. {
  537. io_service_.work_started();
  538. signal_state* state = get_signal_state();
  539. static_mutex::scoped_lock lock(state->mutex_);
  540. registration* reg = impl.signals_;
  541. while (reg)
  542. {
  543. if (reg->undelivered_ > 0)
  544. {
  545. --reg->undelivered_;
  546. op->signal_number_ = reg->signal_number_;
  547. io_service_.post_deferred_completion(op);
  548. return;
  549. }
  550. reg = reg->next_in_set_;
  551. }
  552. impl.queue_.push(op);
  553. }
  554. } // namespace detail
  555. } // namespace asio
  556. } // namespace boost
  557. #include <boost/asio/detail/pop_options.hpp>
  558. #endif // BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP