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