File indexing completed on 2024-11-15 09:02:39
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP
0012 #define BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #include <cstring>
0021 #include <stdexcept>
0022 #include <boost/asio/detail/signal_blocker.hpp>
0023 #include <boost/asio/detail/signal_set_service.hpp>
0024 #include <boost/asio/detail/static_mutex.hpp>
0025 #include <boost/asio/detail/throw_exception.hpp>
0026
0027 #if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0028 # include <boost/asio/detail/io_uring_service.hpp>
0029 #else
0030 # include <boost/asio/detail/reactor.hpp>
0031 #endif
0032
0033 #include <boost/asio/detail/push_options.hpp>
0034
0035 namespace boost {
0036 namespace asio {
0037 namespace detail {
0038
0039 struct signal_state
0040 {
0041
0042 static_mutex mutex_;
0043
0044
0045 int read_descriptor_;
0046
0047
0048 int write_descriptor_;
0049
0050
0051 bool fork_prepared_;
0052
0053
0054 class signal_set_service* service_list_;
0055
0056
0057 std::size_t registration_count_[max_signal_number];
0058
0059
0060 signal_set_base::flags_t flags_[max_signal_number];
0061 };
0062
0063 signal_state* get_signal_state()
0064 {
0065 static signal_state state = {
0066 BOOST_ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0,
0067 { 0 }, { signal_set_base::flags_t() } };
0068 return &state;
0069 }
0070
0071 void boost_asio_signal_handler(int signal_number)
0072 {
0073 #if defined(BOOST_ASIO_WINDOWS) \
0074 || defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0075 || defined(__CYGWIN__)
0076 signal_set_service::deliver_signal(signal_number);
0077 #else
0078
0079
0080 int saved_errno = errno;
0081 signal_state* state = get_signal_state();
0082 signed_size_type result = ::write(state->write_descriptor_,
0083 &signal_number, sizeof(signal_number));
0084 (void)result;
0085 errno = saved_errno;
0086 #endif
0087
0088
0089
0090 #if defined(BOOST_ASIO_HAS_SIGNAL) && !defined(BOOST_ASIO_HAS_SIGACTION)
0091 ::signal(signal_number, boost_asio_signal_handler);
0092 #endif
0093 }
0094
0095 #if !defined(BOOST_ASIO_WINDOWS) \
0096 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0097 && !defined(__CYGWIN__)
0098 class signal_set_service::pipe_read_op :
0099 # if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0100 public io_uring_operation
0101 # else
0102 public reactor_op
0103 # endif
0104 {
0105 public:
0106 # if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0107 pipe_read_op()
0108 : io_uring_operation(boost::system::error_code(), &pipe_read_op::do_prepare,
0109 &pipe_read_op::do_perform, pipe_read_op::do_complete)
0110 {
0111 }
0112
0113 static void do_prepare(io_uring_operation*, ::io_uring_sqe* sqe)
0114 {
0115 signal_state* state = get_signal_state();
0116
0117 int fd = state->read_descriptor_;
0118 ::io_uring_prep_poll_add(sqe, fd, POLLIN);
0119 }
0120
0121 static bool do_perform(io_uring_operation*, bool)
0122 {
0123 signal_state* state = get_signal_state();
0124
0125 int fd = state->read_descriptor_;
0126 int signal_number = 0;
0127 while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))
0128 if (signal_number >= 0 && signal_number < max_signal_number)
0129 signal_set_service::deliver_signal(signal_number);
0130
0131 return false;
0132 }
0133 # else
0134 pipe_read_op()
0135 : reactor_op(boost::system::error_code(),
0136 &pipe_read_op::do_perform, pipe_read_op::do_complete)
0137 {
0138 }
0139
0140 static status do_perform(reactor_op*)
0141 {
0142 signal_state* state = get_signal_state();
0143
0144 int fd = state->read_descriptor_;
0145 int signal_number = 0;
0146 while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))
0147 if (signal_number >= 0 && signal_number < max_signal_number)
0148 signal_set_service::deliver_signal(signal_number);
0149
0150 return not_done;
0151 }
0152 # endif
0153
0154 static void do_complete(void* , operation* base,
0155 const boost::system::error_code& ,
0156 std::size_t )
0157 {
0158 pipe_read_op* o(static_cast<pipe_read_op*>(base));
0159 delete o;
0160 }
0161 };
0162 #endif
0163
0164
0165
0166 signal_set_service::signal_set_service(execution_context& context)
0167 : execution_context_service_base<signal_set_service>(context),
0168 scheduler_(boost::asio::use_service<scheduler_impl>(context)),
0169 #if !defined(BOOST_ASIO_WINDOWS) \
0170 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0171 && !defined(__CYGWIN__)
0172 # if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0173 io_uring_service_(boost::asio::use_service<io_uring_service>(context)),
0174 # else
0175 reactor_(boost::asio::use_service<reactor>(context)),
0176 # endif
0177 #endif
0178
0179
0180 next_(0),
0181 prev_(0)
0182 {
0183 get_signal_state()->mutex_.init();
0184
0185 #if !defined(BOOST_ASIO_WINDOWS) \
0186 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0187 && !defined(__CYGWIN__)
0188 # if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0189 io_uring_service_.init_task();
0190 # else
0191 reactor_.init_task();
0192 # endif
0193 #endif
0194
0195
0196
0197 for (int i = 0; i < max_signal_number; ++i)
0198 registrations_[i] = 0;
0199
0200 add_service(this);
0201 }
0202
0203 signal_set_service::~signal_set_service()
0204 {
0205 remove_service(this);
0206 }
0207
0208 void signal_set_service::shutdown()
0209 {
0210 remove_service(this);
0211
0212 op_queue<operation> ops;
0213
0214 for (int i = 0; i < max_signal_number; ++i)
0215 {
0216 registration* reg = registrations_[i];
0217 while (reg)
0218 {
0219 ops.push(*reg->queue_);
0220 reg = reg->next_in_table_;
0221 }
0222 }
0223
0224 scheduler_.abandon_operations(ops);
0225 }
0226
0227 void signal_set_service::notify_fork(execution_context::fork_event fork_ev)
0228 {
0229 #if !defined(BOOST_ASIO_WINDOWS) \
0230 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0231 && !defined(__CYGWIN__)
0232 signal_state* state = get_signal_state();
0233 static_mutex::scoped_lock lock(state->mutex_);
0234
0235 switch (fork_ev)
0236 {
0237 case execution_context::fork_prepare:
0238 {
0239 int read_descriptor = state->read_descriptor_;
0240 state->fork_prepared_ = true;
0241 lock.unlock();
0242 # if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0243 (void)read_descriptor;
0244 io_uring_service_.deregister_io_object(io_object_data_);
0245 io_uring_service_.cleanup_io_object(io_object_data_);
0246 # else
0247 reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_);
0248 reactor_.cleanup_descriptor_data(reactor_data_);
0249 # endif
0250 }
0251 break;
0252 case execution_context::fork_parent:
0253 if (state->fork_prepared_)
0254 {
0255 int read_descriptor = state->read_descriptor_;
0256 state->fork_prepared_ = false;
0257 lock.unlock();
0258 # if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0259 (void)read_descriptor;
0260 io_uring_service_.register_internal_io_object(io_object_data_,
0261 io_uring_service::read_op, new pipe_read_op);
0262 # else
0263 reactor_.register_internal_descriptor(reactor::read_op,
0264 read_descriptor, reactor_data_, new pipe_read_op);
0265 # endif
0266 }
0267 break;
0268 case execution_context::fork_child:
0269 if (state->fork_prepared_)
0270 {
0271 boost::asio::detail::signal_blocker blocker;
0272 close_descriptors();
0273 open_descriptors();
0274 int read_descriptor = state->read_descriptor_;
0275 state->fork_prepared_ = false;
0276 lock.unlock();
0277 # if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0278 (void)read_descriptor;
0279 io_uring_service_.register_internal_io_object(io_object_data_,
0280 io_uring_service::read_op, new pipe_read_op);
0281 # else
0282 reactor_.register_internal_descriptor(reactor::read_op,
0283 read_descriptor, reactor_data_, new pipe_read_op);
0284 # endif
0285 }
0286 break;
0287 default:
0288 break;
0289 }
0290 #else
0291
0292
0293 (void)fork_ev;
0294 #endif
0295
0296
0297 }
0298
0299 void signal_set_service::construct(
0300 signal_set_service::implementation_type& impl)
0301 {
0302 impl.signals_ = 0;
0303 }
0304
0305 void signal_set_service::destroy(
0306 signal_set_service::implementation_type& impl)
0307 {
0308 boost::system::error_code ignored_ec;
0309 clear(impl, ignored_ec);
0310 cancel(impl, ignored_ec);
0311 }
0312
0313 boost::system::error_code signal_set_service::add(
0314 signal_set_service::implementation_type& impl, int signal_number,
0315 signal_set_base::flags_t f, boost::system::error_code& ec)
0316 {
0317
0318 if (signal_number < 0 || signal_number >= max_signal_number)
0319 {
0320 ec = boost::asio::error::invalid_argument;
0321 return ec;
0322 }
0323
0324
0325 #if !defined(BOOST_ASIO_HAS_SIGACTION)
0326 if (f != signal_set_base::flags::dont_care)
0327 {
0328 ec = boost::asio::error::operation_not_supported;
0329 return ec;
0330 }
0331 #endif
0332
0333 signal_state* state = get_signal_state();
0334 static_mutex::scoped_lock lock(state->mutex_);
0335
0336
0337 registration** insertion_point = &impl.signals_;
0338 registration* next = impl.signals_;
0339 while (next && next->signal_number_ < signal_number)
0340 {
0341 insertion_point = &next->next_in_set_;
0342 next = next->next_in_set_;
0343 }
0344
0345
0346 if (next == 0 || next->signal_number_ != signal_number)
0347 {
0348 registration* new_registration = new registration;
0349
0350 #if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
0351
0352 if (state->registration_count_[signal_number] == 0)
0353 {
0354 # if defined(BOOST_ASIO_HAS_SIGACTION)
0355 using namespace std;
0356 struct sigaction sa;
0357 memset(&sa, 0, sizeof(sa));
0358 sa.sa_handler = boost_asio_signal_handler;
0359 sigfillset(&sa.sa_mask);
0360 if (f != signal_set_base::flags::dont_care)
0361 sa.sa_flags = static_cast<int>(f);
0362 if (::sigaction(signal_number, &sa, 0) == -1)
0363 # else
0364 if (::signal(signal_number, boost_asio_signal_handler) == SIG_ERR)
0365 # endif
0366 {
0367 # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0368 ec = boost::asio::error::invalid_argument;
0369 # else
0370 ec = boost::system::error_code(errno,
0371 boost::asio::error::get_system_category());
0372 # endif
0373 delete new_registration;
0374 return ec;
0375 }
0376 # if defined(BOOST_ASIO_HAS_SIGACTION)
0377 state->flags_[signal_number] = f;
0378 # endif
0379 }
0380 # if defined(BOOST_ASIO_HAS_SIGACTION)
0381
0382 else if (f != signal_set_base::flags::dont_care)
0383 {
0384 if (f != state->flags_[signal_number])
0385 {
0386 using namespace std;
0387 if (state->flags_[signal_number] != signal_set_base::flags::dont_care)
0388 {
0389 ec = boost::asio::error::invalid_argument;
0390 delete new_registration;
0391 return ec;
0392 }
0393 struct sigaction sa;
0394 memset(&sa, 0, sizeof(sa));
0395 sa.sa_handler = boost_asio_signal_handler;
0396 sigfillset(&sa.sa_mask);
0397 sa.sa_flags = static_cast<int>(f);
0398 if (::sigaction(signal_number, &sa, 0) == -1)
0399 {
0400 ec = boost::system::error_code(errno,
0401 boost::asio::error::get_system_category());
0402 delete new_registration;
0403 return ec;
0404 }
0405 state->flags_[signal_number] = f;
0406 }
0407 }
0408 # endif
0409 #endif
0410
0411
0412 new_registration->signal_number_ = signal_number;
0413 new_registration->queue_ = &impl.queue_;
0414 new_registration->next_in_set_ = next;
0415 *insertion_point = new_registration;
0416
0417
0418 new_registration->next_in_table_ = registrations_[signal_number];
0419 if (registrations_[signal_number])
0420 registrations_[signal_number]->prev_in_table_ = new_registration;
0421 registrations_[signal_number] = new_registration;
0422
0423 ++state->registration_count_[signal_number];
0424 }
0425
0426 ec = boost::system::error_code();
0427 return ec;
0428 }
0429
0430 boost::system::error_code signal_set_service::remove(
0431 signal_set_service::implementation_type& impl,
0432 int signal_number, boost::system::error_code& ec)
0433 {
0434
0435 if (signal_number < 0 || signal_number >= max_signal_number)
0436 {
0437 ec = boost::asio::error::invalid_argument;
0438 return ec;
0439 }
0440
0441 signal_state* state = get_signal_state();
0442 static_mutex::scoped_lock lock(state->mutex_);
0443
0444
0445 registration** deletion_point = &impl.signals_;
0446 registration* reg = impl.signals_;
0447 while (reg && reg->signal_number_ < signal_number)
0448 {
0449 deletion_point = ®->next_in_set_;
0450 reg = reg->next_in_set_;
0451 }
0452
0453 if (reg != 0 && reg->signal_number_ == signal_number)
0454 {
0455 #if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
0456
0457 if (state->registration_count_[signal_number] == 1)
0458 {
0459 # if defined(BOOST_ASIO_HAS_SIGACTION)
0460 using namespace std;
0461 struct sigaction sa;
0462 memset(&sa, 0, sizeof(sa));
0463 sa.sa_handler = SIG_DFL;
0464 if (::sigaction(signal_number, &sa, 0) == -1)
0465 # else
0466 if (::signal(signal_number, SIG_DFL) == SIG_ERR)
0467 # endif
0468 {
0469 # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0470 ec = boost::asio::error::invalid_argument;
0471 # else
0472 ec = boost::system::error_code(errno,
0473 boost::asio::error::get_system_category());
0474 # endif
0475 return ec;
0476 }
0477 # if defined(BOOST_ASIO_HAS_SIGACTION)
0478 state->flags_[signal_number] = signal_set_base::flags_t();
0479 # endif
0480 }
0481 #endif
0482
0483
0484 *deletion_point = reg->next_in_set_;
0485
0486
0487 if (registrations_[signal_number] == reg)
0488 registrations_[signal_number] = reg->next_in_table_;
0489 if (reg->prev_in_table_)
0490 reg->prev_in_table_->next_in_table_ = reg->next_in_table_;
0491 if (reg->next_in_table_)
0492 reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;
0493
0494 --state->registration_count_[signal_number];
0495
0496 delete reg;
0497 }
0498
0499 ec = boost::system::error_code();
0500 return ec;
0501 }
0502
0503 boost::system::error_code signal_set_service::clear(
0504 signal_set_service::implementation_type& impl,
0505 boost::system::error_code& ec)
0506 {
0507 signal_state* state = get_signal_state();
0508 static_mutex::scoped_lock lock(state->mutex_);
0509
0510 while (registration* reg = impl.signals_)
0511 {
0512 #if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION)
0513
0514 if (state->registration_count_[reg->signal_number_] == 1)
0515 {
0516 # if defined(BOOST_ASIO_HAS_SIGACTION)
0517 using namespace std;
0518 struct sigaction sa;
0519 memset(&sa, 0, sizeof(sa));
0520 sa.sa_handler = SIG_DFL;
0521 if (::sigaction(reg->signal_number_, &sa, 0) == -1)
0522 # else
0523 if (::signal(reg->signal_number_, SIG_DFL) == SIG_ERR)
0524 # endif
0525 {
0526 # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
0527 ec = boost::asio::error::invalid_argument;
0528 # else
0529 ec = boost::system::error_code(errno,
0530 boost::asio::error::get_system_category());
0531 # endif
0532 return ec;
0533 }
0534 # if defined(BOOST_ASIO_HAS_SIGACTION)
0535 state->flags_[reg->signal_number_] = signal_set_base::flags_t();
0536 # endif
0537 }
0538 #endif
0539
0540
0541 if (registrations_[reg->signal_number_] == reg)
0542 registrations_[reg->signal_number_] = reg->next_in_table_;
0543 if (reg->prev_in_table_)
0544 reg->prev_in_table_->next_in_table_ = reg->next_in_table_;
0545 if (reg->next_in_table_)
0546 reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;
0547
0548 --state->registration_count_[reg->signal_number_];
0549
0550 impl.signals_ = reg->next_in_set_;
0551 delete reg;
0552 }
0553
0554 ec = boost::system::error_code();
0555 return ec;
0556 }
0557
0558 boost::system::error_code signal_set_service::cancel(
0559 signal_set_service::implementation_type& impl,
0560 boost::system::error_code& ec)
0561 {
0562 BOOST_ASIO_HANDLER_OPERATION((scheduler_.context(),
0563 "signal_set", &impl, 0, "cancel"));
0564
0565 op_queue<operation> ops;
0566 {
0567 signal_state* state = get_signal_state();
0568 static_mutex::scoped_lock lock(state->mutex_);
0569
0570 while (signal_op* op = impl.queue_.front())
0571 {
0572 op->ec_ = boost::asio::error::operation_aborted;
0573 impl.queue_.pop();
0574 ops.push(op);
0575 }
0576 }
0577
0578 scheduler_.post_deferred_completions(ops);
0579
0580 ec = boost::system::error_code();
0581 return ec;
0582 }
0583
0584 void signal_set_service::cancel_ops_by_key(
0585 signal_set_service::implementation_type& impl, void* cancellation_key)
0586 {
0587 op_queue<operation> ops;
0588 {
0589 op_queue<signal_op> other_ops;
0590 signal_state* state = get_signal_state();
0591 static_mutex::scoped_lock lock(state->mutex_);
0592
0593 while (signal_op* op = impl.queue_.front())
0594 {
0595 impl.queue_.pop();
0596 if (op->cancellation_key_ == cancellation_key)
0597 {
0598 op->ec_ = boost::asio::error::operation_aborted;
0599 ops.push(op);
0600 }
0601 else
0602 other_ops.push(op);
0603 }
0604
0605 impl.queue_.push(other_ops);
0606 }
0607
0608 scheduler_.post_deferred_completions(ops);
0609 }
0610
0611 void signal_set_service::deliver_signal(int signal_number)
0612 {
0613 signal_state* state = get_signal_state();
0614 static_mutex::scoped_lock lock(state->mutex_);
0615
0616 signal_set_service* service = state->service_list_;
0617 while (service)
0618 {
0619 op_queue<operation> ops;
0620
0621 registration* reg = service->registrations_[signal_number];
0622 while (reg)
0623 {
0624 if (reg->queue_->empty())
0625 {
0626 ++reg->undelivered_;
0627 }
0628 else
0629 {
0630 while (signal_op* op = reg->queue_->front())
0631 {
0632 op->signal_number_ = signal_number;
0633 reg->queue_->pop();
0634 ops.push(op);
0635 }
0636 }
0637
0638 reg = reg->next_in_table_;
0639 }
0640
0641 service->scheduler_.post_deferred_completions(ops);
0642
0643 service = service->next_;
0644 }
0645 }
0646
0647 void signal_set_service::add_service(signal_set_service* service)
0648 {
0649 signal_state* state = get_signal_state();
0650 static_mutex::scoped_lock lock(state->mutex_);
0651
0652 #if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
0653
0654 if (state->service_list_ == 0)
0655 open_descriptors();
0656 #endif
0657
0658
0659
0660 if (state->service_list_ != 0)
0661 {
0662 if (!BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,
0663 service->scheduler_.concurrency_hint())
0664 || !BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,
0665 state->service_list_->scheduler_.concurrency_hint()))
0666 {
0667 std::logic_error ex(
0668 "Thread-unsafe execution context objects require "
0669 "exclusive access to signal handling.");
0670 boost::asio::detail::throw_exception(ex);
0671 }
0672 }
0673
0674
0675 service->next_ = state->service_list_;
0676 service->prev_ = 0;
0677 if (state->service_list_)
0678 state->service_list_->prev_ = service;
0679 state->service_list_ = service;
0680
0681 #if !defined(BOOST_ASIO_WINDOWS) \
0682 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0683 && !defined(__CYGWIN__)
0684
0685 int read_descriptor = state->read_descriptor_;
0686 lock.unlock();
0687 # if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0688 (void)read_descriptor;
0689 service->io_uring_service_.register_internal_io_object(
0690 service->io_object_data_, io_uring_service::read_op, new pipe_read_op);
0691 # else
0692 service->reactor_.register_internal_descriptor(reactor::read_op,
0693 read_descriptor, service->reactor_data_, new pipe_read_op);
0694 # endif
0695 #endif
0696
0697
0698 }
0699
0700 void signal_set_service::remove_service(signal_set_service* service)
0701 {
0702 signal_state* state = get_signal_state();
0703 static_mutex::scoped_lock lock(state->mutex_);
0704
0705 if (service->next_ || service->prev_ || state->service_list_ == service)
0706 {
0707 #if !defined(BOOST_ASIO_WINDOWS) \
0708 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0709 && !defined(__CYGWIN__)
0710
0711 int read_descriptor = state->read_descriptor_;
0712 lock.unlock();
0713 # if defined(BOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
0714 (void)read_descriptor;
0715 service->io_uring_service_.deregister_io_object(service->io_object_data_);
0716 service->io_uring_service_.cleanup_io_object(service->io_object_data_);
0717 lock.lock();
0718 # else
0719 service->reactor_.deregister_internal_descriptor(
0720 read_descriptor, service->reactor_data_);
0721 service->reactor_.cleanup_descriptor_data(service->reactor_data_);
0722 lock.lock();
0723 # endif
0724 #endif
0725
0726
0727
0728
0729 if (state->service_list_ == service)
0730 state->service_list_ = service->next_;
0731 if (service->prev_)
0732 service->prev_->next_ = service->next_;
0733 if (service->next_)
0734 service->next_->prev_= service->prev_;
0735 service->next_ = 0;
0736 service->prev_ = 0;
0737
0738 #if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
0739
0740 if (state->service_list_ == 0)
0741 close_descriptors();
0742 #endif
0743 }
0744 }
0745
0746 void signal_set_service::open_descriptors()
0747 {
0748 #if !defined(BOOST_ASIO_WINDOWS) \
0749 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0750 && !defined(__CYGWIN__)
0751 signal_state* state = get_signal_state();
0752
0753 int pipe_fds[2];
0754 if (::pipe(pipe_fds) == 0)
0755 {
0756 state->read_descriptor_ = pipe_fds[0];
0757 ::fcntl(state->read_descriptor_, F_SETFL, O_NONBLOCK);
0758
0759 state->write_descriptor_ = pipe_fds[1];
0760 ::fcntl(state->write_descriptor_, F_SETFL, O_NONBLOCK);
0761
0762 #if defined(FD_CLOEXEC)
0763 ::fcntl(state->read_descriptor_, F_SETFD, FD_CLOEXEC);
0764 ::fcntl(state->write_descriptor_, F_SETFD, FD_CLOEXEC);
0765 #endif
0766 }
0767 else
0768 {
0769 boost::system::error_code ec(errno,
0770 boost::asio::error::get_system_category());
0771 boost::asio::detail::throw_error(ec, "signal_set_service pipe");
0772 }
0773 #endif
0774
0775
0776 }
0777
0778 void signal_set_service::close_descriptors()
0779 {
0780 #if !defined(BOOST_ASIO_WINDOWS) \
0781 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
0782 && !defined(__CYGWIN__)
0783 signal_state* state = get_signal_state();
0784
0785 if (state->read_descriptor_ != -1)
0786 ::close(state->read_descriptor_);
0787 state->read_descriptor_ = -1;
0788
0789 if (state->write_descriptor_ != -1)
0790 ::close(state->write_descriptor_);
0791 state->write_descriptor_ = -1;
0792 #endif
0793
0794
0795 }
0796
0797 void signal_set_service::start_wait_op(
0798 signal_set_service::implementation_type& impl, signal_op* op)
0799 {
0800 scheduler_.work_started();
0801
0802 signal_state* state = get_signal_state();
0803 static_mutex::scoped_lock lock(state->mutex_);
0804
0805 registration* reg = impl.signals_;
0806 while (reg)
0807 {
0808 if (reg->undelivered_ > 0)
0809 {
0810 --reg->undelivered_;
0811 op->signal_number_ = reg->signal_number_;
0812 scheduler_.post_deferred_completion(op);
0813 return;
0814 }
0815
0816 reg = reg->next_in_set_;
0817 }
0818
0819 impl.queue_.push(op);
0820 }
0821
0822 }
0823 }
0824 }
0825
0826 #include <boost/asio/detail/pop_options.hpp>
0827
0828 #endif