Changeset 69467


Ignore:
Timestamp:
Mar 2, 2011, 8:27:32 AM (7 years ago)
Author:
chris_kohlhoff
Message:
  • Add support for the fork() system call. Programs that use fork must call io_service.notify_fork() at the appropriate times. Two new examples have been added showing how to use this feature. Refs #3238, #4162.
  • Clean up the handling of errors reported by the close() system call. In particular, assume that most operating systems won't have close() fail with EWOULDBLOCK, but if it does then set blocking mode and restart the call. If any other error occurs we assume the descriptor is closed. Refs #3307.
  • EV_ONESHOT seems to cause problems on some versions of Mac OS X, with the io_service destructor getting stuck inside the close() system call. Use EV_CLEAR instead. Refs #5021.
  • Include function name in exception what() messages.
  • Fix insufficient initialisers warning with MinGW.
  • Make the shutdown_service() member functions private.
  • Add archetypes for testing socket option functions.
  • Add missing lock in signal_set_service::cancel().
  • The signal header needs to be included in signal_set_service.hpp so that we can use constants like NSIG and SIGRTMAX.
  • Don't use Boost.Thread's convenience header. Use the header file that is specifically for the boost::thread class instead.
Location:
trunk
Files:
7 added
81 edited

Legend:

Unmodified
Added
Removed
  • trunk/boost/asio/basic_datagram_socket.hpp

    r69194 r69467  
    160160    boost::system::error_code ec;
    161161    std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
    162     boost::asio::detail::throw_error(ec);
     162    boost::asio::detail::throw_error(ec, "send");
    163163    return s;
    164164  }
     
    188188    std::size_t s = this->service.send(
    189189        this->implementation, buffers, flags, ec);
    190     boost::asio::detail::throw_error(ec);
     190    boost::asio::detail::throw_error(ec, "send");
    191191    return s;
    192192  }
     
    336336    std::size_t s = this->service.send_to(
    337337        this->implementation, buffers, destination, 0, ec);
    338     boost::asio::detail::throw_error(ec);
     338    boost::asio::detail::throw_error(ec, "send_to");
    339339    return s;
    340340  }
     
    363363    std::size_t s = this->service.send_to(
    364364        this->implementation, buffers, destination, flags, ec);
    365     boost::asio::detail::throw_error(ec);
     365    boost::asio::detail::throw_error(ec, "send_to");
    366366    return s;
    367367  }
     
    511511    std::size_t s = this->service.receive(
    512512        this->implementation, buffers, 0, ec);
    513     boost::asio::detail::throw_error(ec);
     513    boost::asio::detail::throw_error(ec, "receive");
    514514    return s;
    515515  }
     
    540540    std::size_t s = this->service.receive(
    541541        this->implementation, buffers, flags, ec);
    542     boost::asio::detail::throw_error(ec);
     542    boost::asio::detail::throw_error(ec, "receive");
    543543    return s;
    544544  }
     
    689689    std::size_t s = this->service.receive_from(
    690690        this->implementation, buffers, sender_endpoint, 0, ec);
    691     boost::asio::detail::throw_error(ec);
     691    boost::asio::detail::throw_error(ec, "receive_from");
    692692    return s;
    693693  }
     
    716716    std::size_t s = this->service.receive_from(
    717717        this->implementation, buffers, sender_endpoint, flags, ec);
    718     boost::asio::detail::throw_error(ec);
     718    boost::asio::detail::throw_error(ec, "receive_from");
    719719    return s;
    720720  }
  • trunk/boost/asio/basic_deadline_timer.hpp

    r69194 r69467  
    163163    boost::system::error_code ec;
    164164    this->service.expires_at(this->implementation, expiry_time, ec);
    165     boost::asio::detail::throw_error(ec);
     165    boost::asio::detail::throw_error(ec, "expires_at");
    166166  }
    167167
     
    182182    boost::system::error_code ec;
    183183    this->service.expires_from_now(this->implementation, expiry_time, ec);
    184     boost::asio::detail::throw_error(ec);
     184    boost::asio::detail::throw_error(ec, "expires_from_now");
    185185  }
    186186
     
    211211    boost::system::error_code ec;
    212212    std::size_t s = this->service.cancel(this->implementation, ec);
    213     boost::asio::detail::throw_error(ec);
     213    boost::asio::detail::throw_error(ec, "cancel");
    214214    return s;
    215215  }
     
    270270    boost::system::error_code ec;
    271271    std::size_t s = this->service.cancel_one(this->implementation, ec);
    272     boost::asio::detail::throw_error(ec);
     272    boost::asio::detail::throw_error(ec, "cancel_one");
    273273    return s;
    274274  }
     
    340340    std::size_t s = this->service.expires_at(
    341341        this->implementation, expiry_time, ec);
    342     boost::asio::detail::throw_error(ec);
     342    boost::asio::detail::throw_error(ec, "expires_at");
    343343    return s;
    344344  }
     
    409409    std::size_t s = this->service.expires_from_now(
    410410        this->implementation, expiry_time, ec);
    411     boost::asio::detail::throw_error(ec);
     411    boost::asio::detail::throw_error(ec, "expires_from_now");
    412412    return s;
    413413  }
     
    453453    boost::system::error_code ec;
    454454    this->service.wait(this->implementation, ec);
    455     boost::asio::detail::throw_error(ec);
     455    boost::asio::detail::throw_error(ec, "wait");
    456456  }
    457457
  • trunk/boost/asio/basic_raw_socket.hpp

    r69194 r69467  
    159159    boost::system::error_code ec;
    160160    std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
    161     boost::asio::detail::throw_error(ec);
     161    boost::asio::detail::throw_error(ec, "send");
    162162    return s;
    163163  }
     
    186186    std::size_t s = this->service.send(
    187187        this->implementation, buffers, flags, ec);
    188     boost::asio::detail::throw_error(ec);
     188    boost::asio::detail::throw_error(ec, "send");
    189189    return s;
    190190  }
     
    331331    std::size_t s = this->service.send_to(
    332332        this->implementation, buffers, destination, 0, ec);
    333     boost::asio::detail::throw_error(ec);
     333    boost::asio::detail::throw_error(ec, "send_to");
    334334    return s;
    335335  }
     
    358358    std::size_t s = this->service.send_to(
    359359        this->implementation, buffers, destination, flags, ec);
    360     boost::asio::detail::throw_error(ec);
     360    boost::asio::detail::throw_error(ec, "send_to");
    361361    return s;
    362362  }
     
    506506    std::size_t s = this->service.receive(
    507507        this->implementation, buffers, 0, ec);
    508     boost::asio::detail::throw_error(ec);
     508    boost::asio::detail::throw_error(ec, "receive");
    509509    return s;
    510510  }
     
    535535    std::size_t s = this->service.receive(
    536536        this->implementation, buffers, flags, ec);
    537     boost::asio::detail::throw_error(ec);
     537    boost::asio::detail::throw_error(ec, "receive");
    538538    return s;
    539539  }
     
    684684    std::size_t s = this->service.receive_from(
    685685        this->implementation, buffers, sender_endpoint, 0, ec);
    686     boost::asio::detail::throw_error(ec);
     686    boost::asio::detail::throw_error(ec, "receive_from");
    687687    return s;
    688688  }
     
    711711    std::size_t s = this->service.receive_from(
    712712        this->implementation, buffers, sender_endpoint, flags, ec);
    713     boost::asio::detail::throw_error(ec);
     713    boost::asio::detail::throw_error(ec, "receive_from");
    714714    return s;
    715715  }
  • trunk/boost/asio/basic_seq_packet_socket.hpp

    r69194 r69467  
    167167    std::size_t s = this->service.send(
    168168        this->implementation, buffers, flags, ec);
    169     boost::asio::detail::throw_error(ec);
     169    boost::asio::detail::throw_error(ec, "send");
    170170    return s;
    171171  }
     
    277277    std::size_t s = this->service.receive(
    278278        this->implementation, buffers, 0, out_flags, ec);
    279     boost::asio::detail::throw_error(ec);
     279    boost::asio::detail::throw_error(ec, "receive");
    280280    return s;
    281281  }
     
    324324    std::size_t s = this->service.receive(
    325325        this->implementation, buffers, in_flags, out_flags, ec);
    326     boost::asio::detail::throw_error(ec);
     326    boost::asio::detail::throw_error(ec, "receive");
    327327    return s;
    328328  }
  • trunk/boost/asio/basic_serial_port.hpp

    r69194 r69467  
    8989    boost::system::error_code ec;
    9090    this->service.open(this->implementation, device, ec);
    91     boost::asio::detail::throw_error(ec);
     91    boost::asio::detail::throw_error(ec, "open");
    9292  }
    9393
     
    109109    boost::system::error_code ec;
    110110    this->service.open(this->implementation, device, ec);
    111     boost::asio::detail::throw_error(ec);
     111    boost::asio::detail::throw_error(ec, "open");
    112112  }
    113113
     
    130130    boost::system::error_code ec;
    131131    this->service.assign(this->implementation, native_serial_port, ec);
    132     boost::asio::detail::throw_error(ec);
     132    boost::asio::detail::throw_error(ec, "assign");
    133133  }
    134134
     
    173173    boost::system::error_code ec;
    174174    this->service.open(this->implementation, device, ec);
    175     boost::asio::detail::throw_error(ec);
     175    boost::asio::detail::throw_error(ec, "open");
    176176  }
    177177
     
    203203    boost::system::error_code ec;
    204204    this->service.assign(this->implementation, native_serial_port, ec);
    205     boost::asio::detail::throw_error(ec);
     205    boost::asio::detail::throw_error(ec, "assign");
    206206  }
    207207
     
    238238    boost::system::error_code ec;
    239239    this->service.close(this->implementation, ec);
    240     boost::asio::detail::throw_error(ec);
     240    boost::asio::detail::throw_error(ec, "close");
    241241  }
    242242
     
    289289    boost::system::error_code ec;
    290290    this->service.cancel(this->implementation, ec);
    291     boost::asio::detail::throw_error(ec);
     291    boost::asio::detail::throw_error(ec, "cancel");
    292292  }
    293293
     
    316316    boost::system::error_code ec;
    317317    this->service.send_break(this->implementation, ec);
    318     boost::asio::detail::throw_error(ec);
     318    boost::asio::detail::throw_error(ec, "send_break");
    319319  }
    320320
     
    351351    boost::system::error_code ec;
    352352    this->service.set_option(this->implementation, option, ec);
    353     boost::asio::detail::throw_error(ec);
     353    boost::asio::detail::throw_error(ec, "set_option");
    354354  }
    355355
     
    397397    boost::system::error_code ec;
    398398    this->service.get_option(this->implementation, option, ec);
    399     boost::asio::detail::throw_error(ec);
     399    boost::asio::detail::throw_error(ec, "get_option");
    400400  }
    401401
     
    455455    boost::system::error_code ec;
    456456    std::size_t s = this->service.write_some(this->implementation, buffers, ec);
    457     boost::asio::detail::throw_error(ec);
     457    boost::asio::detail::throw_error(ec, "write_some");
    458458    return s;
    459459  }
     
    562562    boost::system::error_code ec;
    563563    std::size_t s = this->service.read_some(this->implementation, buffers, ec);
    564     boost::asio::detail::throw_error(ec);
     564    boost::asio::detail::throw_error(ec, "read_some");
    565565    return s;
    566566  }
  • trunk/boost/asio/basic_signal_set.hpp

    r69198 r69467  
    126126    boost::system::error_code ec;
    127127    this->service.add(this->implementation, signal_number_1, ec);
    128     boost::asio::detail::throw_error(ec);
     128    boost::asio::detail::throw_error(ec, "add");
    129129  }
    130130
     
    151151    boost::system::error_code ec;
    152152    this->service.add(this->implementation, signal_number_1, ec);
    153     boost::asio::detail::throw_error(ec);
     153    boost::asio::detail::throw_error(ec, "add");
    154154    this->service.add(this->implementation, signal_number_2, ec);
    155     boost::asio::detail::throw_error(ec);
     155    boost::asio::detail::throw_error(ec, "add");
    156156  }
    157157
     
    181181    boost::system::error_code ec;
    182182    this->service.add(this->implementation, signal_number_1, ec);
    183     boost::asio::detail::throw_error(ec);
     183    boost::asio::detail::throw_error(ec, "add");
    184184    this->service.add(this->implementation, signal_number_2, ec);
    185     boost::asio::detail::throw_error(ec);
     185    boost::asio::detail::throw_error(ec, "add");
    186186    this->service.add(this->implementation, signal_number_3, ec);
    187     boost::asio::detail::throw_error(ec);
     187    boost::asio::detail::throw_error(ec, "add");
    188188  }
    189189
     
    201201    boost::system::error_code ec;
    202202    this->service.add(this->implementation, signal_number, ec);
    203     boost::asio::detail::throw_error(ec);
     203    boost::asio::detail::throw_error(ec, "add");
    204204  }
    205205
     
    235235    boost::system::error_code ec;
    236236    this->service.remove(this->implementation, signal_number, ec);
    237     boost::asio::detail::throw_error(ec);
     237    boost::asio::detail::throw_error(ec, "remove");
    238238  }
    239239
     
    269269    boost::system::error_code ec;
    270270    this->service.clear(this->implementation, ec);
    271     boost::asio::detail::throw_error(ec);
     271    boost::asio::detail::throw_error(ec, "clear");
    272272  }
    273273
     
    311311    boost::system::error_code ec;
    312312    this->service.cancel(this->implementation, ec);
    313     boost::asio::detail::throw_error(ec);
     313    boost::asio::detail::throw_error(ec, "cancel");
    314314  }
    315315
  • trunk/boost/asio/basic_socket.hpp

    r69194 r69467  
    8888    boost::system::error_code ec;
    8989    this->service.open(this->implementation, protocol, ec);
    90     boost::asio::detail::throw_error(ec);
     90    boost::asio::detail::throw_error(ec, "open");
    9191  }
    9292
     
    112112    boost::system::error_code ec;
    113113    this->service.open(this->implementation, endpoint.protocol(), ec);
    114     boost::asio::detail::throw_error(ec);
     114    boost::asio::detail::throw_error(ec, "open");
    115115    this->service.bind(this->implementation, endpoint, ec);
    116     boost::asio::detail::throw_error(ec);
     116    boost::asio::detail::throw_error(ec, "bind");
    117117  }
    118118
     
    136136    boost::system::error_code ec;
    137137    this->service.assign(this->implementation, protocol, native_socket, ec);
    138     boost::asio::detail::throw_error(ec);
     138    boost::asio::detail::throw_error(ec, "assign");
    139139  }
    140140
     
    185185    boost::system::error_code ec;
    186186    this->service.open(this->implementation, protocol, ec);
    187     boost::asio::detail::throw_error(ec);
     187    boost::asio::detail::throw_error(ec, "open");
    188188  }
    189189
     
    228228    boost::system::error_code ec;
    229229    this->service.assign(this->implementation, protocol, native_socket, ec);
    230     boost::asio::detail::throw_error(ec);
     230    boost::asio::detail::throw_error(ec, "assign");
    231231  }
    232232
     
    260260   * with the boost::asio::error::operation_aborted error.
    261261   *
    262    * @throws boost::system::system_error Thrown on failure.
     262   * @throws boost::system::system_error Thrown on failure. Note that, even if
     263   * the function indicates an error, the underlying descriptor is closed.
    263264   *
    264265   * @note For portable behaviour with respect to graceful closure of a
     
    269270    boost::system::error_code ec;
    270271    this->service.close(this->implementation, ec);
    271     boost::asio::detail::throw_error(ec);
     272    boost::asio::detail::throw_error(ec, "close");
    272273  }
    273274
     
    278279   * with the boost::asio::error::operation_aborted error.
    279280   *
    280    * @param ec Set to indicate what error occurred, if any.
     281   * @param ec Set to indicate what error occurred, if any. Note that, even if
     282   * the function indicates an error, the underlying descriptor is closed.
    281283   *
    282284   * @par Example
     
    367369    boost::system::error_code ec;
    368370    this->service.cancel(this->implementation, ec);
    369     boost::asio::detail::throw_error(ec);
     371    boost::asio::detail::throw_error(ec, "cancel");
    370372  }
    371373
     
    430432    boost::system::error_code ec;
    431433    bool b = this->service.at_mark(this->implementation, ec);
    432     boost::asio::detail::throw_error(ec);
     434    boost::asio::detail::throw_error(ec, "at_mark");
    433435    return b;
    434436  }
     
    463465    boost::system::error_code ec;
    464466    std::size_t s = this->service.available(this->implementation, ec);
    465     boost::asio::detail::throw_error(ec);
     467    boost::asio::detail::throw_error(ec, "available");
    466468    return s;
    467469  }
     
    504506    boost::system::error_code ec;
    505507    this->service.bind(this->implementation, endpoint, ec);
    506     boost::asio::detail::throw_error(ec);
     508    boost::asio::detail::throw_error(ec, "bind");
    507509  }
    508510
     
    565567    {
    566568      this->service.open(this->implementation, peer_endpoint.protocol(), ec);
    567       boost::asio::detail::throw_error(ec);
     569      boost::asio::detail::throw_error(ec, "connect");
    568570    }
    569571    this->service.connect(this->implementation, peer_endpoint, ec);
    570     boost::asio::detail::throw_error(ec);
     572    boost::asio::detail::throw_error(ec, "connect");
    571573  }
    572574
     
    717719    boost::system::error_code ec;
    718720    this->service.set_option(this->implementation, option, ec);
    719     boost::asio::detail::throw_error(ec);
     721    boost::asio::detail::throw_error(ec, "set_option");
    720722  }
    721723
     
    806808    boost::system::error_code ec;
    807809    this->service.get_option(this->implementation, option, ec);
    808     boost::asio::detail::throw_error(ec);
     810    boost::asio::detail::throw_error(ec, "get_option");
    809811  }
    810812
     
    883885    boost::system::error_code ec;
    884886    this->service.io_control(this->implementation, command, ec);
    885     boost::asio::detail::throw_error(ec);
     887    boost::asio::detail::throw_error(ec, "io_control");
    886888  }
    887889
     
    953955    boost::system::error_code ec;
    954956    this->service.non_blocking(this->implementation, mode, ec);
    955     boost::asio::detail::throw_error(ec);
     957    boost::asio::detail::throw_error(ec, "non_blocking");
    956958  }
    957959
     
    11531155    boost::system::error_code ec;
    11541156    this->service.native_non_blocking(this->implementation, mode, ec);
    1155     boost::asio::detail::throw_error(ec);
     1157    boost::asio::detail::throw_error(ec, "native_non_blocking");
    11561158  }
    11571159
     
    12661268    boost::system::error_code ec;
    12671269    endpoint_type ep = this->service.local_endpoint(this->implementation, ec);
    1268     boost::asio::detail::throw_error(ec);
     1270    boost::asio::detail::throw_error(ec, "local_endpoint");
    12691271    return ep;
    12701272  }
     
    13151317    boost::system::error_code ec;
    13161318    endpoint_type ep = this->service.remote_endpoint(this->implementation, ec);
    1317     boost::asio::detail::throw_error(ec);
     1319    boost::asio::detail::throw_error(ec, "remote_endpoint");
    13181320    return ep;
    13191321  }
     
    13661368    boost::system::error_code ec;
    13671369    this->service.shutdown(this->implementation, what, ec);
    1368     boost::asio::detail::throw_error(ec);
     1370    boost::asio::detail::throw_error(ec, "shutdown");
    13691371  }
    13701372
  • trunk/boost/asio/basic_socket_acceptor.hpp

    r69194 r69467  
    103103    boost::system::error_code ec;
    104104    this->service.open(this->implementation, protocol, ec);
    105     boost::asio::detail::throw_error(ec);
     105    boost::asio::detail::throw_error(ec, "open");
    106106  }
    107107
     
    139139    boost::system::error_code ec;
    140140    this->service.open(this->implementation, endpoint.protocol(), ec);
    141     boost::asio::detail::throw_error(ec);
     141    boost::asio::detail::throw_error(ec, "open");
    142142    if (reuse_addr)
    143143    {
    144144      this->service.set_option(this->implementation,
    145145          socket_base::reuse_address(true), ec);
    146       boost::asio::detail::throw_error(ec);
     146      boost::asio::detail::throw_error(ec, "set_option");
    147147    }
    148148    this->service.bind(this->implementation, endpoint, ec);
    149     boost::asio::detail::throw_error(ec);
     149    boost::asio::detail::throw_error(ec, "bind");
    150150    this->service.listen(this->implementation,
    151151        socket_base::max_connections, ec);
    152     boost::asio::detail::throw_error(ec);
     152    boost::asio::detail::throw_error(ec, "listen");
    153153  }
    154154
     
    174174    boost::system::error_code ec;
    175175    this->service.assign(this->implementation, protocol, native_acceptor, ec);
    176     boost::asio::detail::throw_error(ec);
     176    boost::asio::detail::throw_error(ec, "assign");
    177177  }
    178178
     
    196196    boost::system::error_code ec;
    197197    this->service.open(this->implementation, protocol, ec);
    198     boost::asio::detail::throw_error(ec);
     198    boost::asio::detail::throw_error(ec, "open");
    199199  }
    200200
     
    240240    boost::system::error_code ec;
    241241    this->service.assign(this->implementation, protocol, native_acceptor, ec);
    242     boost::asio::detail::throw_error(ec);
     242    boost::asio::detail::throw_error(ec, "assign");
    243243  }
    244244
     
    287287    boost::system::error_code ec;
    288288    this->service.bind(this->implementation, endpoint, ec);
    289     boost::asio::detail::throw_error(ec);
     289    boost::asio::detail::throw_error(ec, "bind");
    290290  }
    291291
     
    332332    boost::system::error_code ec;
    333333    this->service.listen(this->implementation, backlog, ec);
    334     boost::asio::detail::throw_error(ec);
     334    boost::asio::detail::throw_error(ec, "listen");
    335335  }
    336336
     
    376376    boost::system::error_code ec;
    377377    this->service.close(this->implementation, ec);
    378     boost::asio::detail::throw_error(ec);
     378    boost::asio::detail::throw_error(ec, "close");
    379379  }
    380380
     
    440440    boost::system::error_code ec;
    441441    this->service.cancel(this->implementation, ec);
    442     boost::asio::detail::throw_error(ec);
     442    boost::asio::detail::throw_error(ec, "cancel");
    443443  }
    444444
     
    482482    boost::system::error_code ec;
    483483    this->service.set_option(this->implementation, option, ec);
    484     boost::asio::detail::throw_error(ec);
     484    boost::asio::detail::throw_error(ec, "set_option");
    485485  }
    486486
     
    545545    boost::system::error_code ec;
    546546    this->service.get_option(this->implementation, option, ec);
    547     boost::asio::detail::throw_error(ec);
     547    boost::asio::detail::throw_error(ec, "get_option");
    548548  }
    549549
     
    607607    boost::system::error_code ec;
    608608    this->service.io_control(this->implementation, command, ec);
    609     boost::asio::detail::throw_error(ec);
     609    boost::asio::detail::throw_error(ec, "io_control");
    610610  }
    611611
     
    675675    boost::system::error_code ec;
    676676    this->service.non_blocking(this->implementation, mode, ec);
    677     boost::asio::detail::throw_error(ec);
     677    boost::asio::detail::throw_error(ec, "non_blocking");
    678678  }
    679679
     
    735735    boost::system::error_code ec;
    736736    this->service.native_non_blocking(this->implementation, mode, ec);
    737     boost::asio::detail::throw_error(ec);
     737    boost::asio::detail::throw_error(ec, "native_non_blocking");
    738738  }
    739739
     
    778778    boost::system::error_code ec;
    779779    endpoint_type ep = this->service.local_endpoint(this->implementation, ec);
    780     boost::asio::detail::throw_error(ec);
     780    boost::asio::detail::throw_error(ec, "local_endpoint");
    781781    return ep;
    782782  }
     
    832832    boost::system::error_code ec;
    833833    this->service.accept(this->implementation, peer, 0, ec);
    834     boost::asio::detail::throw_error(ec);
     834    boost::asio::detail::throw_error(ec, "accept");
    835835  }
    836836
     
    945945    boost::system::error_code ec;
    946946    this->service.accept(this->implementation, peer, &peer_endpoint, ec);
    947     boost::asio::detail::throw_error(ec);
     947    boost::asio::detail::throw_error(ec, "accept");
    948948  }
    949949
  • trunk/boost/asio/basic_socket_streambuf.hpp

    r69194 r69467  
    224224    boost::system::error_code ec;
    225225    timer_service_->expires_at(timer_implementation_, expiry_time, ec);
    226     boost::asio::detail::throw_error(ec);
     226    boost::asio::detail::throw_error(ec, "expires_at");
    227227
    228228    start_timer();
     
    253253    boost::system::error_code ec;
    254254    timer_service_->expires_from_now(timer_implementation_, expiry_time, ec);
    255     boost::asio::detail::throw_error(ec);
     255    boost::asio::detail::throw_error(ec, "expires_from_now");
    256256
    257257    start_timer();
  • trunk/boost/asio/basic_stream_socket.hpp

    r69194 r69467  
    165165    std::size_t s = this->service.send(
    166166        this->implementation, buffers, 0, ec);
    167     boost::asio::detail::throw_error(ec);
     167    boost::asio::detail::throw_error(ec, "send");
    168168    return s;
    169169  }
     
    203203    std::size_t s = this->service.send(
    204204        this->implementation, buffers, flags, ec);
    205     boost::asio::detail::throw_error(ec);
     205    boost::asio::detail::throw_error(ec, "send");
    206206    return s;
    207207  }
     
    360360    boost::system::error_code ec;
    361361    std::size_t s = this->service.receive(this->implementation, buffers, 0, ec);
    362     boost::asio::detail::throw_error(ec);
     362    boost::asio::detail::throw_error(ec, "receive");
    363363    return s;
    364364  }
     
    401401    std::size_t s = this->service.receive(
    402402        this->implementation, buffers, flags, ec);
    403     boost::asio::detail::throw_error(ec);
     403    boost::asio::detail::throw_error(ec, "receive");
    404404    return s;
    405405  }
     
    561561    boost::system::error_code ec;
    562562    std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
    563     boost::asio::detail::throw_error(ec);
     563    boost::asio::detail::throw_error(ec, "write_some");
    564564    return s;
    565565  }
     
    668668    boost::system::error_code ec;
    669669    std::size_t s = this->service.receive(this->implementation, buffers, 0, ec);
    670     boost::asio::detail::throw_error(ec);
     670    boost::asio::detail::throw_error(ec, "read_some");
    671671    return s;
    672672  }
  • trunk/boost/asio/datagram_socket_service.hpp

    r69194 r69467  
    9191  }
    9292
    93   /// Destroy all user-defined handler objects owned by the service.
    94   void shutdown_service()
    95   {
    96     service_impl_.shutdown_service();
    97   }
    98 
    9993  /// Construct a new datagram socket implementation.
    10094  void construct(implementation_type& impl)
     
    341335
    342336private:
     337  // Destroy all user-defined handler objects owned by the service.
     338  void shutdown_service()
     339  {
     340    service_impl_.shutdown_service();
     341  }
     342
    343343  // The platform-specific implementation.
    344344  service_impl_type service_impl_;
  • trunk/boost/asio/deadline_timer_service.hpp

    r69194 r69467  
    7373  }
    7474
    75   /// Destroy all user-defined handler objects owned by the service.
    76   void shutdown_service()
    77   {
    78     service_impl_.shutdown_service();
    79   }
    80 
    8175  /// Construct a new timer implementation.
    8276  void construct(implementation_type& impl)
     
    144138
    145139private:
     140  // Destroy all user-defined handler objects owned by the service.
     141  void shutdown_service()
     142  {
     143    service_impl_.shutdown_service();
     144  }
     145
    146146  // The platform-specific implementation.
    147147  service_impl_type service_impl_;
  • trunk/boost/asio/detail/dev_poll_reactor.hpp

    r69198 r69467  
    6565  BOOST_ASIO_DECL void shutdown_service();
    6666
     67  // Recreate internal descriptors following a fork.
     68  BOOST_ASIO_DECL void fork_service(
     69      boost::asio::io_service::fork_event event);
     70
    6771  // Initialise the task.
    6872  BOOST_ASIO_DECL void init_task();
     
    99103      per_descriptor_data&, bool closing);
    100104
     105  // Cancel any operations that are running against the descriptor and remove
     106  // its registration from the reactor.
     107  BOOST_ASIO_DECL void deregister_internal_descriptor(
     108      socket_type descriptor, per_descriptor_data&);
     109
    101110  // Add a new timer queue to the reactor.
    102111  template <typename Time_Traits>
     
    149158      const boost::system::error_code& ec);
    150159
     160  // Helper class used to reregister descriptors after a fork.
     161  class fork_helper;
     162  friend class fork_helper;
     163
    151164  // Add a pending event entry for the given descriptor.
    152165  BOOST_ASIO_DECL ::pollfd& add_pending_event_change(int descriptor);
  • trunk/boost/asio/detail/epoll_reactor.hpp

    r69198 r69467  
    5353    friend class object_pool_access;
    5454    mutex mutex_;
     55    int descriptor_;
    5556    op_queue<reactor_op> op_queue_[max_ops];
    5657    bool shutdown_;
     
    7172  BOOST_ASIO_DECL void shutdown_service();
    7273
     74  // Recreate internal descriptors following a fork.
     75  BOOST_ASIO_DECL void fork_service(
     76      boost::asio::io_service::fork_event event);
     77
    7378  // Initialise the task.
    7479  BOOST_ASIO_DECL void init_task();
     
    108113      per_descriptor_data& descriptor_data, bool closing);
    109114
     115  // Remote the descriptor's registration from the reactor.
     116  BOOST_ASIO_DECL void deregister_internal_descriptor(
     117      socket_type descriptor, per_descriptor_data& descriptor_data);
     118
    110119  // Add a new timer queue to the reactor.
    111120  template <typename Time_Traits>
  • trunk/boost/asio/detail/eventfd_select_interrupter.hpp

    r68086 r69467  
    3636  BOOST_ASIO_DECL ~eventfd_select_interrupter();
    3737
     38  // Recreate the interrupter's descriptors. Used after a fork.
     39  BOOST_ASIO_DECL void recreate();
     40
    3841  // Interrupt the select call.
    3942  BOOST_ASIO_DECL void interrupt();
     
    4952
    5053private:
     54  // Open the descriptors. Throws on error.
     55  BOOST_ASIO_DECL void open_descriptors();
     56
     57  // Close the descriptors.
     58  BOOST_ASIO_DECL void close_descriptors();
     59
    5160  // The read end of a connection used to interrupt the select call. This file
    5261  // descriptor is passed to select such that when it is time to stop, a single
  • trunk/boost/asio/detail/impl/descriptor_ops.ipp

    r69194 r69467  
    4444  if (d != -1)
    4545  {
    46     if (state & internal_non_blocking)
    47     {
     46    errno = 0;
     47    result = error_wrapper(::close(d), ec);
     48
     49    if (result != 0
     50        && (ec == boost::asio::error::would_block
     51          || ec == boost::asio::error::try_again))
     52    {
     53      // According to UNIX Network Programming Vol. 1, it is possible for
     54      // close() to fail with EWOULDBLOCK under certain circumstances. What
     55      // isn't clear is the state of the descriptor after this error. The one
     56      // current OS where this behaviour is seen, Windows, says that the socket
     57      // remains open. Therefore we'll put the descriptor back into blocking
     58      // mode and have another attempt at closing it.
    4859#if defined(__SYMBIAN32__)
    4960      int flags = ::fcntl(d, F_GETFL, 0);
     
    5465      ::ioctl(d, FIONBIO, &arg);
    5566#endif // defined(__SYMBIAN32__)
    56       state &= ~internal_non_blocking;
    57     }
    58 
    59     errno = 0;
    60     result = error_wrapper(::close(d), ec);
     67      state &= ~non_blocking;
     68
     69      errno = 0;
     70      result = error_wrapper(::close(d), ec);
     71    }
    6172  }
    6273
  • trunk/boost/asio/detail/impl/dev_poll_reactor.ipp

    r69198 r69467  
    2020#if defined(BOOST_ASIO_HAS_DEV_POLL)
    2121
     22#include <boost/assert.hpp>
    2223#include <boost/asio/detail/dev_poll_reactor.hpp>
    2324#include <boost/asio/detail/throw_error.hpp>
     
    3940{
    4041  // Add the interrupter's descriptor to /dev/poll.
    41   ::pollfd ev = { 0 };
     42  ::pollfd ev = { 0, 0, 0 };
    4243  ev.fd = interrupter_.read_descriptor();
    4344  ev.events = POLLIN | POLLERR;
     
    6566  timer_queues_.get_all_timers(ops);
    6667}
     68
     69// Helper class to re-register all descriptors with /dev/poll.
     70class dev_poll_reactor::fork_helper
     71{
     72public:
     73  fork_helper(dev_poll_reactor* reactor, short events)
     74    : reactor_(reactor), events_(events)
     75  {
     76  }
     77
     78  bool set(int descriptor)
     79  {
     80    ::pollfd& ev = reactor_->add_pending_event_change(descriptor);
     81    ev.events = events_;
     82    return true;
     83  }
     84
     85private:
     86  dev_poll_reactor* reactor_;
     87  short events_;
     88};
     89
     90void dev_poll_reactor::fork_service(boost::asio::io_service::fork_event event)
     91{
     92  if (event == boost::asio::io_service::fork_child)
     93  {
     94    detail::mutex::scoped_lock lock(mutex_);
     95
     96    if (dev_poll_fd_ != -1)
     97      ::close(dev_poll_fd_);
     98    dev_poll_fd_ = -1;
     99    dev_poll_fd_ = do_dev_poll_create();
     100
     101    interrupter_.recreate();
     102
     103    // Add the interrupter's descriptor to /dev/poll.
     104    ::pollfd ev = { 0, 0, 0 };
     105    ev.fd = interrupter_.read_descriptor();
     106    ev.events = POLLIN | POLLERR;
     107    ev.revents = 0;
     108    ::write(dev_poll_fd_, &ev, sizeof(ev));
     109
     110    // Re-register all descriptors with /dev/poll. The changes will be written
     111    // to the /dev/poll descriptor the next time the reactor is run.
     112    op_queue<operation> ops;
     113    fork_helper read_op_helper(this, POLLERR | POLLHUP | POLLIN);
     114    op_queue_[read_op].get_descriptors(read_op_helper, ops);
     115    fork_helper write_op_helper(this, POLLERR | POLLHUP | POLLOUT);
     116    op_queue_[write_op].get_descriptors(write_op_helper, ops);
     117    fork_helper except_op_helper(this, POLLERR | POLLHUP | POLLPRI);
     118    op_queue_[except_op].get_descriptors(except_op_helper, ops);
     119    interrupter_.interrupt();
     120
     121    // The ops op_queue will always be empty because the fork_helper's set()
     122    // member function never returns false.
     123    BOOST_ASSERT(ops.empty());
     124  }
     125}
    67126
    68127void dev_poll_reactor::init_task()
     
    162221  // Cancel any outstanding operations associated with the descriptor.
    163222  cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
     223}
     224
     225void dev_poll_reactor::deregister_internal_descriptor(
     226    socket_type descriptor, dev_poll_reactor::per_descriptor_data&)
     227{
     228  boost::asio::detail::mutex::scoped_lock lock(mutex_);
     229
     230  // Remove the descriptor from /dev/poll. Since this function is only called
     231  // during a fork, we can apply the change immediately.
     232  ::pollfd ev = { 0, 0, 0 };
     233  ev.fd = descriptor;
     234  ev.events = POLLREMOVE;
     235  ev.revents = 0;
     236  ::write(dev_poll_fd_, &ev, sizeof(ev));
     237
     238  // Destroy all operations associated with the descriptor.
     239  op_queue<operation> ops;
     240  boost::system::error_code ec;
     241  for (int i = 0; i < max_ops; ++i)
     242    op_queue_[i].cancel_operations(descriptor, ops, ec);
    164243}
    165244
     
    200279
    201280  // Block on the /dev/poll descriptor.
    202   ::pollfd events[128] = { { 0 } };
    203   ::dvpoll dp = { 0 };
     281  ::pollfd events[128] = { { 0, 0, 0 } };
     282  ::dvpoll dp = { 0, 0, 0 };
    204283  dp.dp_fds = events;
    205284  dp.dp_nfds = 128;
     
    249328        // is no operation pending, so if we do not remove the descriptor we
    250329        // can end up in a tight polling loop.
    251         ::pollfd ev = { 0 };
     330        ::pollfd ev = { 0, 0, 0 };
    252331        ev.fd = descriptor;
    253332        ev.events = POLLREMOVE;
     
    257336      else
    258337      {
    259         ::pollfd ev = { 0 };
     338        ::pollfd ev = { 0, 0, 0 };
    260339        ev.fd = descriptor;
    261340        ev.events = POLLERR | POLLHUP;
  • trunk/boost/asio/detail/impl/epoll_reactor.ipp

    r69198 r69467  
    6363epoll_reactor::~epoll_reactor()
    6464{
    65   close(epoll_fd_);
     65  if (epoll_fd_ != -1)
     66    close(epoll_fd_);
    6667  if (timer_fd_ != -1)
    6768    close(timer_fd_);
     
    8788}
    8889
     90void epoll_reactor::fork_service(boost::asio::io_service::fork_event event)
     91{
     92  if (event == boost::asio::io_service::fork_child)
     93  {
     94    if (epoll_fd_ != -1)
     95      ::close(epoll_fd_);
     96    epoll_fd_ = -1;
     97    epoll_fd_ = do_epoll_create();
     98
     99    if (timer_fd_ != -1)
     100      ::close(timer_fd_);
     101    timer_fd_ = -1;
     102    timer_fd_ = do_timerfd_create();
     103
     104    interrupter_.recreate();
     105
     106    // Add the interrupter's descriptor to epoll.
     107    epoll_event ev = { 0, { 0 } };
     108    ev.events = EPOLLIN | EPOLLERR | EPOLLET;
     109    ev.data.ptr = &interrupter_;
     110    epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
     111    interrupter_.interrupt();
     112
     113    // Add the timer descriptor to epoll.
     114    if (timer_fd_ != -1)
     115    {
     116      ev.events = EPOLLIN | EPOLLERR;
     117      ev.data.ptr = &timer_fd_;
     118      epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
     119    }
     120
     121    update_timeout();
     122
     123    // Re-register all descriptors with epoll.
     124    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
     125    for (descriptor_state* state = registered_descriptors_.first();
     126        state != 0; state = state->next_)
     127    {
     128      ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
     129      ev.data.ptr = state;
     130      int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, state->descriptor_, &ev);
     131      if (result != 0)
     132      {
     133        boost::system::error_code ec(errno,
     134            boost::asio::error::get_system_category());
     135        boost::asio::detail::throw_error(ec, "epoll re-registration");
     136      }
     137    }
     138  }
     139}
     140
    89141void epoll_reactor::init_task()
    90142{
     
    98150
    99151  descriptor_data = registered_descriptors_.alloc();
     152  descriptor_data->descriptor_ = descriptor;
    100153  descriptor_data->shutdown_ = false;
    101154
     
    119172
    120173  descriptor_data = registered_descriptors_.alloc();
     174  descriptor_data->descriptor_ = descriptor;
    121175  descriptor_data->shutdown_ = false;
    122176  descriptor_data->op_queue_[op_type].push(op);
     
    125179
    126180  epoll_event ev = { 0, { 0 } };
    127   ev.events = EPOLLERR | EPOLLHUP | EPOLLET;
    128   switch (op_type)
    129   {
    130   case read_op: ev.events |= EPOLLIN; break;
    131   case write_op: ev.events |= EPOLLOUT; break;
    132   case except_op: ev.events |= EPOLLPRI; break;
    133   default: break;
    134   };
     181  ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
    135182  ev.data.ptr = descriptor_data;
    136183  int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
     
    244291    }
    245292
     293    descriptor_data->descriptor_ = -1;
    246294    descriptor_data->shutdown_ = true;
    247295
     
    254302
    255303    io_service_.post_deferred_completions(ops);
     304  }
     305}
     306
     307void epoll_reactor::deregister_internal_descriptor(socket_type descriptor,
     308    epoll_reactor::per_descriptor_data& descriptor_data)
     309{
     310  if (!descriptor_data)
     311    return;
     312
     313  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
     314  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
     315
     316  if (!descriptor_data->shutdown_)
     317  {
     318    epoll_event ev = { 0, { 0 } };
     319    epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
     320
     321    op_queue<operation> ops;
     322    for (int i = 0; i < max_ops; ++i)
     323      ops.push(descriptor_data->op_queue_[i]);
     324
     325    descriptor_data->descriptor_ = -1;
     326    descriptor_data->shutdown_ = true;
     327
     328    descriptor_lock.unlock();
     329
     330    registered_descriptors_.free(descriptor_data);
     331    descriptor_data = 0;
     332
     333    descriptors_lock.unlock();
    256334  }
    257335}
  • trunk/boost/asio/detail/impl/eventfd_select_interrupter.ipp

    r69198 r69467  
    4040
    4141eventfd_select_interrupter::eventfd_select_interrupter()
     42{
     43  open_descriptors();
     44}
     45
     46void eventfd_select_interrupter::open_descriptors()
    4247{
    4348#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
     
    9095eventfd_select_interrupter::~eventfd_select_interrupter()
    9196{
     97  close_descriptors();
     98}
     99
     100void eventfd_select_interrupter::close_descriptors()
     101{
    92102  if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
    93103    ::close(write_descriptor_);
    94104  if (read_descriptor_ != -1)
    95105    ::close(read_descriptor_);
     106}
     107
     108void eventfd_select_interrupter::recreate()
     109{
     110  close_descriptors();
     111
     112  write_descriptor_ = -1;
     113  read_descriptor_ = -1;
     114
     115  open_descriptors();
    96116}
    97117
  • trunk/boost/asio/detail/impl/kqueue_reactor.ipp

    r69198 r69467  
    4848    shutdown_(false)
    4949{
    50   // The interrupter is put into a permanently readable state. Whenever we
    51   // want to interrupt the blocked kevent call we register a one-shot read
    52   // operation against the descriptor.
     50  // The interrupter is put into a permanently readable state. Whenever we want
     51  // to interrupt the blocked kevent call we register a read operation against
     52  // the descriptor.
    5353  interrupter_.interrupt();
    5454}
     
    7878}
    7979
     80void kqueue_reactor::fork_service(boost::asio::io_service::fork_event event)
     81{
     82  if (event == boost::asio::io_service::fork_child)
     83  {
     84    // The kqueue descriptor is automatically closed in the child.
     85    kqueue_fd_ = -1;
     86    kqueue_fd_ = do_kqueue_create();
     87
     88    interrupter_.recreate();
     89
     90    // Re-register all descriptors with kqueue.
     91    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
     92    for (descriptor_state* state = registered_descriptors_.first();
     93        state != 0; state = state->next_)
     94    {
     95      struct kevent events[2];
     96      int num_events = 0;
     97
     98      if (!state->op_queue_[read_op].empty())
     99        BOOST_ASIO_KQUEUE_EV_SET(&events[num_events++], state->descriptor_,
     100            EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, state);
     101      else if (!state->op_queue_[except_op].empty())
     102        BOOST_ASIO_KQUEUE_EV_SET(&events[num_events++], state->descriptor_,
     103            EVFILT_READ, EV_ADD | EV_CLEAR, EV_OOBAND, 0, state);
     104
     105      if (!state->op_queue_[write_op].empty())
     106        BOOST_ASIO_KQUEUE_EV_SET(&events[num_events++], state->descriptor_,
     107            EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, state);
     108
     109      if (num_events && ::kevent(kqueue_fd_, events, num_events, 0, 0, 0) == -1)
     110      {
     111        boost::system::error_code error(errno,
     112            boost::asio::error::get_system_category());
     113        boost::asio::detail::throw_error(error);
     114      }
     115    }
     116  }
     117}
     118
    80119void kqueue_reactor::init_task()
    81120{
     
    83122}
    84123
    85 int kqueue_reactor::register_descriptor(socket_type,
     124int kqueue_reactor::register_descriptor(socket_type descriptor,
    86125    kqueue_reactor::per_descriptor_data& descriptor_data)
    87126{
     
    89128
    90129  descriptor_data = registered_descriptors_.alloc();
     130  descriptor_data->descriptor_ = descriptor;
    91131  descriptor_data->shutdown_ = false;
    92132
     
    101141
    102142  descriptor_data = registered_descriptors_.alloc();
     143  descriptor_data->descriptor_ = descriptor;
    103144  descriptor_data->shutdown_ = false;
    104145  descriptor_data->op_queue_[op_type].push(op);
     
    109150  case read_op:
    110151    BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
    111         EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
     152        EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
    112153    break;
    113154  case write_op:
    114155    BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
    115         EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
     156        EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
    116157    break;
    117158  case except_op:
    118159    BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
    119         EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
     160        EV_ADD | EV_CLEAR, EV_OOBAND, 0, descriptor_data);
    120161    break;
    121162  }
     
    171212    case read_op:
    172213      BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
    173           EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
     214          EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
    174215      break;
    175216    case write_op:
    176217      BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
    177           EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
     218          EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
    178219      break;
    179220    case except_op:
     
    181222        return; // Already registered for read events.
    182223      BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
    183           EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
     224          EV_ADD | EV_CLEAR, EV_OOBAND, 0, descriptor_data);
    184225      break;
    185226    }
     
    256297    }
    257298
     299    descriptor_data->descriptor_ = -1;
    258300    descriptor_data->shutdown_ = true;
    259301
     
    266308
    267309    io_service_.post_deferred_completions(ops);
     310  }
     311}
     312
     313void kqueue_reactor::deregister_internal_descriptor(socket_type descriptor,
     314    kqueue_reactor::per_descriptor_data& descriptor_data)
     315{
     316  if (!descriptor_data)
     317    return;
     318
     319  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
     320  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
     321
     322  if (!descriptor_data->shutdown_)
     323  {
     324    struct kevent events[2];
     325    BOOST_ASIO_KQUEUE_EV_SET(&events[0], descriptor,
     326        EVFILT_READ, EV_DELETE, 0, 0, 0);
     327    BOOST_ASIO_KQUEUE_EV_SET(&events[1], descriptor,
     328        EVFILT_WRITE, EV_DELETE, 0, 0, 0);
     329    ::kevent(kqueue_fd_, events, 2, 0, 0, 0);
     330
     331    op_queue<operation> ops;
     332    for (int i = 0; i < max_ops; ++i)
     333      ops.push(descriptor_data->op_queue_[i]);
     334
     335    descriptor_data->descriptor_ = -1;
     336    descriptor_data->shutdown_ = true;
     337
     338    descriptor_lock.unlock();
     339
     340    registered_descriptors_.free(descriptor_data);
     341    descriptor_data = 0;
     342
     343    descriptors_lock.unlock();
    268344  }
    269345}
     
    291367    {
    292368      // No need to reset the interrupter since we're leaving the descriptor
    293       // in a ready-to-read state and relying on one-shot notifications.
     369      // in a ready-to-read state and relying on edge-triggered notifications.
    294370    }
    295371    else
     
    340416        if (!descriptor_data->op_queue_[read_op].empty())
    341417          BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
    342               EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
     418              EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
    343419        else if (!descriptor_data->op_queue_[except_op].empty())
    344420          BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
    345               EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
     421              EV_ADD | EV_CLEAR, EV_OOBAND, 0, descriptor_data);
    346422        else
    347423          continue;
     
    350426        if (!descriptor_data->op_queue_[write_op].empty())
    351427          BOOST_ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
    352               EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
     428              EV_ADD | EV_CLEAR, 0, 0, descriptor_data);
    353429        else
    354430          continue;
     
    382458  struct kevent event;
    383459  BOOST_ASIO_KQUEUE_EV_SET(&event, interrupter_.read_descriptor(),
    384       EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_);
     460      EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &interrupter_);
    385461  ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
    386462}
  • trunk/boost/asio/detail/impl/pipe_select_interrupter.ipp

    r69198 r69467  
    3939pipe_select_interrupter::pipe_select_interrupter()
    4040{
     41  open_descriptors();
     42}
     43
     44void pipe_select_interrupter::open_descriptors()
     45{
    4146  int pipe_fds[2];
    4247  if (pipe(pipe_fds) == 0)
     
    6267pipe_select_interrupter::~pipe_select_interrupter()
    6368{
     69  close_descriptors();
     70}
     71
     72void pipe_select_interrupter::close_descriptors()
     73{
    6474  if (read_descriptor_ != -1)
    6575    ::close(read_descriptor_);
    6676  if (write_descriptor_ != -1)
    6777    ::close(write_descriptor_);
     78}
     79
     80void pipe_select_interrupter::recreate()
     81{
     82  close_descriptors();
     83
     84  write_descriptor_ = -1;
     85  read_descriptor_ = -1;
     86
     87  open_descriptors();
    6888}
    6989
  • trunk/boost/asio/detail/impl/reactive_descriptor_service.ipp

    r69198 r69467  
    9898  }
    9999
    100   if (descriptor_ops::close(impl.descriptor_, impl.state_, ec) == 0)
    101     construct(impl);
     100  descriptor_ops::close(impl.descriptor_, impl.state_, ec);
     101
     102  // The descriptor is closed by the OS even if close() returns an error.
     103  //
     104  // (Actually, POSIX says the state of the descriptor is unspecified. On
     105  // Linux the descriptor is apparently closed anyway; e.g. see
     106  //   http://lkml.org/lkml/2005/9/10/129
     107  // We'll just have to assume that other OSes follow the same behaviour.)
     108  construct(impl);
    102109
    103110  return ec;
  • trunk/boost/asio/detail/impl/reactive_socket_service_base.ipp

    r69198 r69467  
    7373  }
    7474
    75   if (socket_ops::close(impl.socket_, impl.state_, true, ec) == 0)
    76     construct(impl);
     75  socket_ops::close(impl.socket_, impl.state_, false, ec);
     76
     77  // The descriptor is closed by the OS even if close() returns an error.
     78  //
     79  // (Actually, POSIX says the state of the descriptor is unspecified. On
     80  // Linux the descriptor is apparently closed anyway; e.g. see
     81  //   http://lkml.org/lkml/2005/9/10/129
     82  // We'll just have to assume that other OSes follow the same behaviour. The
     83  // known exception is when Windows's closesocket() function fails with
     84  // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().
     85  construct(impl);
    7786
    7887  return ec;
  • trunk/boost/asio/detail/impl/resolver_service_base.ipp

    r69198 r69467  
    6666}
    6767
     68void resolver_service_base::fork_service(
     69    boost::asio::io_service::fork_event event)
     70{
     71  if (work_thread_)
     72  {
     73    if (event == boost::asio::io_service::fork_prepare)
     74    {
     75      work_io_service_->stop();
     76      work_thread_->join();
     77    }
     78    else
     79    {
     80      work_io_service_->reset();
     81      work_thread_.reset(new boost::asio::detail::thread(
     82            work_io_service_runner(*work_io_service_)));
     83    }
     84  }
     85}
     86
    6887void resolver_service_base::construct(
    6988    resolver_service_base::implementation_type& impl)
  • trunk/boost/asio/detail/impl/select_reactor.ipp

    r69198 r69467  
    8585}
    8686
     87void select_reactor::fork_service(boost::asio::io_service::fork_event event)
     88{
     89  if (event == boost::asio::io_service::fork_child)
     90    interrupter_.recreate();
     91}
     92
    8793void select_reactor::init_task()
    8894{
     
    137143  boost::asio::detail::mutex::scoped_lock lock(mutex_);
    138144  cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted);
     145}
     146
     147void select_reactor::deregister_internal_descriptor(
     148    socket_type descriptor, select_reactor::per_descriptor_data&)
     149{
     150  boost::asio::detail::mutex::scoped_lock lock(mutex_);
     151  op_queue<operation> ops;
     152  for (int i = 0; i < max_ops; ++i)
     153    op_queue_[i].cancel_operations(descriptor, ops);
    139154}
    140155
  • trunk/boost/asio/detail/impl/service_registry.ipp

    r69194 r69467  
    1818#include <boost/asio/detail/config.hpp>
    1919#include <boost/throw_exception.hpp>
     20#include <vector>
    2021#include <boost/asio/detail/service_registry.hpp>
    2122
     
    5152    first_service_ = next_service;
    5253  }
     54}
     55
     56void service_registry::notify_fork(boost::asio::io_service::fork_event event)
     57{
     58  // Make a copy of all of the services while holding the lock. We don't want
     59  // to hold the lock while calling into each service, as it may try to call
     60  // back into this class.
     61  std::vector<boost::asio::io_service::service*> services;
     62  {
     63    boost::asio::detail::mutex::scoped_lock lock(mutex_);
     64    boost::asio::io_service::service* service = first_service_;
     65    while (service)
     66    {
     67      services.push_back(service);
     68      service = service->next_;
     69    }
     70  }
     71
     72  // If processing the fork_prepare event, we want to go in reverse order of
     73  // service registration, which happens to be the existing order of the
     74  // services in the vector. For the other events we want to go in the other
     75  // direction.
     76  std::size_t num_services = services.size();
     77  if (event == boost::asio::io_service::fork_prepare)
     78    for (std::size_t i = 0; i < num_services; ++i)
     79      services[i]->fork_service(event);
     80  else
     81    for (std::size_t i = num_services; i > 0; --i)
     82      services[i - 1]->fork_service(event);
    5383}
    5484
  • trunk/boost/asio/detail/impl/signal_set_service.ipp

    r69198 r69467  
    1818#include <boost/asio/detail/config.hpp>
    1919
    20 #include <signal.h>
    2120#include <cstring>
    2221#include <boost/asio/detail/reactor.hpp>
     22#include <boost/asio/detail/signal_blocker.hpp>
    2323#include <boost/asio/detail/signal_set_service.hpp>
    2424#include <boost/asio/detail/static_mutex.hpp>
     
    4141  int write_descriptor_;
    4242
     43  // Whether the signal state has been prepared for a fork.
     44  bool fork_prepared_;
     45
    4346  // The head of a linked list of all signal_set_service instances.
    4447  class signal_set_service* service_list_;
     
    5154{
    5255  static signal_state state = {
    53     BOOST_ASIO_STATIC_MUTEX_INIT, -1, -1, 0, { 0 } };
     56    BOOST_ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, { 0 } };
    5457  return &state;
    5558}
     
    7073}
    7174
     75#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
     76class signal_set_service::pipe_read_op : public reactor_op
     77{
     78public:
     79  pipe_read_op()
     80    : reactor_op(&pipe_read_op::do_perform, pipe_read_op::do_complete)
     81  {
     82  }
     83
     84  static bool do_perform(reactor_op*)
     85  {
     86    signal_state* state = get_signal_state();
     87
     88    int fd = state->read_descriptor_;
     89    int signal_number = 0;
     90    while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))
     91      if (signal_number >= 0 && signal_number < max_signal_number)
     92        signal_set_service::deliver_signal(signal_number);
     93
     94    return false;
     95  }
     96
     97  static void do_complete(io_service_impl* /*owner*/, operation* base,
     98      boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
     99  {
     100    pipe_read_op* o(static_cast<pipe_read_op*>(base));
     101    delete o;
     102  }
     103};
     104#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
     105
    72106signal_set_service::signal_set_service(
    73107    boost::asio::io_service& io_service)
     
    111145    }
    112146  }
     147}
     148
     149void signal_set_service::fork_service(boost::asio::io_service::fork_event event)
     150{
     151#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
     152  signal_state* state = get_signal_state();
     153  static_mutex::scoped_lock lock(state->mutex_);
     154
     155  switch (event)
     156  {
     157  case boost::asio::io_service::fork_prepare:
     158    reactor_.deregister_internal_descriptor(
     159        state->read_descriptor_, reactor_data_);
     160    state->fork_prepared_ = true;
     161    break;
     162  case boost::asio::io_service::fork_parent:
     163    state->fork_prepared_ = false;
     164    reactor_.register_internal_descriptor(reactor::read_op,
     165        state->read_descriptor_, reactor_data_, new pipe_read_op);
     166    break;
     167  case boost::asio::io_service::fork_child:
     168    if (state->fork_prepared_)
     169    {
     170      boost::asio::detail::signal_blocker blocker;
     171      close_descriptors();
     172      open_descriptors();
     173      state->fork_prepared_ = false;
     174    }
     175    reactor_.register_internal_descriptor(reactor::read_op,
     176        state->read_descriptor_, reactor_data_, new pipe_read_op);
     177    break;
     178  default:
     179    break;
     180  }
     181#else // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
     182  (void)event;
     183#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
    113184}
    114185
     
    324395
    325396  op_queue<operation> ops;
    326   while (signal_op* op = impl.queue_.front())
    327   {
    328     op->ec_ = boost::asio::error::operation_aborted;
    329     impl.queue_.pop();
    330     ops.push(op);
     397  {
     398    signal_state* state = get_signal_state();
     399    static_mutex::scoped_lock lock(state->mutex_);
     400
     401    while (signal_op* op = impl.queue_.front())
     402    {
     403      op->ec_ = boost::asio::error::operation_aborted;
     404      impl.queue_.pop();
     405      ops.push(op);
     406    }
    331407  }
    332408
     
    373449}
    374450
    375 #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
    376 class signal_set_service::pipe_read_op : public reactor_op
    377 {
    378 public:
    379   pipe_read_op()
    380     : reactor_op(&pipe_read_op::do_perform, pipe_read_op::do_complete)
    381   {
    382   }
    383 
    384   static bool do_perform(reactor_op*)
    385   {
    386     signal_state* state = get_signal_state();
    387 
    388     int fd = state->read_descriptor_;
    389     int signal_number = 0;
    390     while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))
    391       if (signal_number >= 0 && signal_number < max_signal_number)
    392         signal_set_service::deliver_signal(signal_number);
    393 
    394     return false;
    395   }
    396 
    397   static void do_complete(io_service_impl* /*owner*/, operation* base,
    398       boost::system::error_code /*ec*/, std::size_t /*bytes_transferred*/)
    399   {
    400     pipe_read_op* o(static_cast<pipe_read_op*>(base));
    401     delete o;
    402   }
    403 };
    404 #endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
    405 
    406451void signal_set_service::add_service(signal_set_service* service)
    407452{
     
    412457  // If this is the first service to be created, open a new pipe.
    413458  if (state->service_list_ == 0)
    414   {
    415     int pipe_fds[2];
    416     if (::pipe(pipe_fds) == 0)
    417     {
    418       state->read_descriptor_ = pipe_fds[0];
    419       ::fcntl(state->read_descriptor_, F_SETFL, O_NONBLOCK);
    420 
    421       state->write_descriptor_ = pipe_fds[1];
    422       ::fcntl(state->write_descriptor_, F_SETFL, O_NONBLOCK);
    423 
    424 #if defined(FD_CLOEXEC)
    425       ::fcntl(state->read_descriptor_, F_SETFD, FD_CLOEXEC);
    426       ::fcntl(state->write_descriptor_, F_SETFD, FD_CLOEXEC);
    427 #endif // defined(FD_CLOEXEC)
    428     }
    429     else
    430     {
    431       boost::system::error_code ec(errno,
    432           boost::asio::error::get_system_category());
    433       boost::asio::detail::throw_error(ec, "signal_set_service pipe");
    434     }
    435   }
     459    open_descriptors();
    436460#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
    437461
     
    476500    // If this is the last service to be removed, close the pipe.
    477501    if (state->service_list_ == 0)
    478     {
    479       ::close(state->read_descriptor_);
    480       state->read_descriptor_ = -1;
    481       ::close(state->write_descriptor_);
    482       state->write_descriptor_ = -1;
    483     }
    484 #endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
    485   }
     502      close_descriptors();
     503#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
     504  }
     505}
     506
     507void signal_set_service::open_descriptors()
     508{
     509#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
     510  signal_state* state = get_signal_state();
     511
     512  int pipe_fds[2];
     513  if (::pipe(pipe_fds) == 0)
     514  {
     515    state->read_descriptor_ = pipe_fds[0];
     516    ::fcntl(state->read_descriptor_, F_SETFL, O_NONBLOCK);
     517
     518    state->write_descriptor_ = pipe_fds[1];
     519    ::fcntl(state->write_descriptor_, F_SETFL, O_NONBLOCK);
     520
     521#if defined(FD_CLOEXEC)
     522    ::fcntl(state->read_descriptor_, F_SETFD, FD_CLOEXEC);
     523    ::fcntl(state->write_descriptor_, F_SETFD, FD_CLOEXEC);
     524#endif // defined(FD_CLOEXEC)
     525  }
     526  else
     527  {
     528    boost::system::error_code ec(errno,
     529        boost::asio::error::get_system_category());
     530    boost::asio::detail::throw_error(ec, "signal_set_service pipe");
     531  }
     532#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
     533}
     534
     535void signal_set_service::close_descriptors()
     536{
     537#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
     538  signal_state* state = get_signal_state();
     539
     540  if (state->read_descriptor_ != -1)
     541    ::close(state->read_descriptor_);
     542  state->read_descriptor_ = -1;
     543
     544  if (state->write_descriptor_ != -1)
     545    ::close(state->write_descriptor_);
     546  state->write_descriptor_ = -1;
     547#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
    486548}
    487549
  • trunk/boost/asio/detail/impl/socket_ops.ipp

    r69194 r69467  
    279279  if (s != invalid_socket)
    280280  {
    281 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
    282     if ((state & non_blocking) && (state & user_set_linger))
    283     {
    284       ioctl_arg_type arg = 0;
    285       ::ioctlsocket(s, FIONBIO, &arg);
    286       state &= ~non_blocking;
    287     }
    288 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
    289     if (state & non_blocking)
    290     {
    291 #if defined(__SYMBIAN32__)
    292       int flags = ::fcntl(s, F_GETFL, 0);
    293       if (flags >= 0)
    294         ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK);
    295 #else // defined(__SYMBIAN32__)
    296       ioctl_arg_type arg = 0;
    297       ::ioctl(s, FIONBIO, &arg);
    298 #endif // defined(__SYMBIAN32__)
    299       state &= ~non_blocking;
    300     }
    301 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
    302 
     281    // We don't want the destructor to block, so set the socket to linger in
     282    // the background. If the user doesn't like this behaviour then they need
     283    // to explicitly close the socket.
    303284    if (destruction && (state & user_set_linger))
    304285    {
     
    317298    result = error_wrapper(::close(s), ec);
    318299#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
     300
     301    if (result != 0
     302        && (ec == boost::asio::error::would_block
     303          || ec == boost::asio::error::try_again))
     304    {
     305      // According to UNIX Network Programming Vol. 1, it is possible for
     306      // close() to fail with EWOULDBLOCK under certain circumstances. What
     307      // isn't clear is the state of the descriptor after this error. The one
     308      // current OS where this behaviour is seen, Windows, says that the socket
     309      // remains open. Therefore we'll put the descriptor back into blocking
     310      // mode and have another attempt at closing it.
     311#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
     312      ioctl_arg_type arg = 0;
     313      ::ioctlsocket(s, FIONBIO, &arg);
     314#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
     315# if defined(__SYMBIAN32__)
     316      int flags = ::fcntl(s, F_GETFL, 0);
     317      if (flags >= 0)
     318        ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK);
     319# else // defined(__SYMBIAN32__)
     320      ioctl_arg_type arg = 0;
     321      ::ioctl(s, FIONBIO, &arg);
     322# endif // defined(__SYMBIAN32__)
     323#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
     324      state &= ~non_blocking;
     325    }
    319326  }
    320327
  • trunk/boost/asio/detail/impl/socket_select_interrupter.ipp

    r68086 r69467  
    3636
    3737socket_select_interrupter::socket_select_interrupter()
     38{
     39  open_descriptors();
     40}
     41
     42void socket_select_interrupter::open_descriptors()
    3843{
    3944  boost::system::error_code ec;
     
    111116socket_select_interrupter::~socket_select_interrupter()
    112117{
     118  close_descriptors();
     119}
     120
     121void socket_select_interrupter::close_descriptors()
     122{
    113123  boost::system::error_code ec;
    114124  socket_ops::state_type state = socket_ops::internal_non_blocking;
     
    117127  if (write_descriptor_ != invalid_socket)
    118128    socket_ops::close(write_descriptor_, state, true, ec);
     129}
     130
     131void socket_select_interrupter::recreate()
     132{
     133  close_descriptors();
     134
     135  write_descriptor_ = invalid_socket;
     136  read_descriptor_ = invalid_socket;
     137
     138  open_descriptors();
    119139}
    120140
  • trunk/boost/asio/detail/kqueue_reactor.hpp

    r69198 r69467  
    6464    friend class object_pool_access;
    6565    mutex mutex_;
     66    int descriptor_;
    6667    op_queue<reactor_op> op_queue_[max_ops];
    6768    bool shutdown_;
     
    8283  BOOST_ASIO_DECL void shutdown_service();
    8384
     85  // Recreate internal descriptors following a fork.
     86  BOOST_ASIO_DECL void fork_service(
     87      boost::asio::io_service::fork_event event);
     88
    8489  // Initialise the task.
    8590  BOOST_ASIO_DECL void init_task();
     
    119124      per_descriptor_data& descriptor_data, bool closing);
    120125
     126  // Remote the descriptor's registration from the reactor.
     127  BOOST_ASIO_DECL void deregister_internal_descriptor(
     128      socket_type descriptor, per_descriptor_data& descriptor_data);
     129
    121130  // Add a new timer queue to the reactor.
    122131  template <typename Time_Traits>
  • trunk/boost/asio/detail/pipe_select_interrupter.hpp

    r68086 r69467  
    3838  BOOST_ASIO_DECL ~pipe_select_interrupter();
    3939
     40  // Recreate the interrupter's descriptors. Used after a fork.
     41  BOOST_ASIO_DECL void recreate();
     42
    4043  // Interrupt the select call.
    4144  BOOST_ASIO_DECL void interrupt();
     
    5154
    5255private:
     56  // Open the descriptors. Throws on error.
     57  BOOST_ASIO_DECL void open_descriptors();
     58
     59  // Close the descriptors.
     60  BOOST_ASIO_DECL void close_descriptors();
     61
    5362  // The read end of a connection used to interrupt the select call. This file
    5463  // descriptor is passed to select such that when it is time to stop, a single
  • trunk/boost/asio/detail/resolver_service_base.hpp

    r68086 r69467  
    4848  // Destroy all user-defined handler objects owned by the service.
    4949  BOOST_ASIO_DECL void shutdown_service();
     50
     51  // Perform any fork-related housekeeping.
     52  BOOST_ASIO_DECL void fork_service(boost::asio::io_service::fork_event event);
    5053
    5154  // Construct a new resolver implementation.
  • trunk/boost/asio/detail/select_reactor.hpp

    r69198 r69467  
    7474  BOOST_ASIO_DECL void shutdown_service();
    7575
     76  // Recreate internal descriptors following a fork.
     77  BOOST_ASIO_DECL void fork_service(
     78      boost::asio::io_service::fork_event event);
     79
    7680  // Initialise the task, but only if the reactor is not in its own thread.
    7781  BOOST_ASIO_DECL void init_task();
     
    108112      per_descriptor_data&, bool closing);
    109113
     114  // Remote the descriptor's registration from the reactor.
     115  BOOST_ASIO_DECL void deregister_internal_descriptor(
     116      socket_type descriptor, per_descriptor_data& descriptor_data);
     117
    110118  // Add a new timer queue to the reactor.
    111119  template <typename Time_Traits>
  • trunk/boost/asio/detail/service_registry.hpp

    r68086 r69467  
    5858  // Destructor.
    5959  BOOST_ASIO_DECL ~service_registry();
     60
     61  // Notify all services of a fork event.
     62  BOOST_ASIO_DECL void notify_fork(boost::asio::io_service::fork_event event);
    6063
    6164  // Get the service object corresponding to the specified service type. Will
  • trunk/boost/asio/detail/signal_set_service.hpp

    r69198 r69467  
    1818#include <boost/asio/detail/config.hpp>
    1919
     20#include <csignal>
    2021#include <cstddef>
    2122#include <boost/asio/error.hpp>
     
    118119  BOOST_ASIO_DECL void shutdown_service();
    119120
     121  // Perform fork-related housekeeping.
     122  BOOST_ASIO_DECL void fork_service(boost::asio::io_service::fork_event event);
     123
    120124  // Construct a new signal_set implementation.
    121125  BOOST_ASIO_DECL void construct(implementation_type& impl);
     
    167171  BOOST_ASIO_DECL static void remove_service(signal_set_service* service);
    168172
     173  // Helper function to create the pipe descriptors.
     174  BOOST_ASIO_DECL static void open_descriptors();
     175
     176  // Helper function to close the pipe descriptors.
     177  BOOST_ASIO_DECL static void close_descriptors();
     178
    169179  // Helper function to start a wait operation.
    170180  BOOST_ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op);
  • trunk/boost/asio/detail/socket_select_interrupter.hpp

    r68086 r69467  
    3939  BOOST_ASIO_DECL ~socket_select_interrupter();
    4040
     41  // Recreate the interrupter's descriptors. Used after a fork.
     42  BOOST_ASIO_DECL void recreate();
     43
    4144  // Interrupt the select call.
    4245  BOOST_ASIO_DECL void interrupt();
     
    5255
    5356private:
     57  // Open the descriptors. Throws on error.
     58  BOOST_ASIO_DECL void open_descriptors();
     59
     60  // Close the descriptors.
     61  BOOST_ASIO_DECL void close_descriptors();
     62
    5463  // The read end of a connection used to interrupt the select call. This file
    5564  // descriptor is passed to select such that when it is time to stop, a single
  • trunk/boost/asio/detail/win_static_mutex.hpp

    r69198 r69467  
    5656};
    5757
    58 #define BOOST_ASIO_WIN_STATIC_MUTEX_INIT { false, { 0 } }
     58#define BOOST_ASIO_WIN_STATIC_MUTEX_INIT { false, { 0, 0, 0, 0, 0, 0 } }
    5959
    6060} // namespace detail
  • trunk/boost/asio/impl/connect.hpp

    r69194 r69467  
    4646  boost::system::error_code ec;
    4747  Iterator result = connect(s, begin, ec);
    48   boost::asio::detail::throw_error(ec);
     48  boost::asio::detail::throw_error(ec, "connect");
    4949  return result;
    5050}
     
    6363  boost::system::error_code ec;
    6464  Iterator result = connect(s, begin, end, ec);
    65   boost::asio::detail::throw_error(ec);
     65  boost::asio::detail::throw_error(ec, "connect");
    6666  return result;
    6767}
     
    8181  boost::system::error_code ec;
    8282  Iterator result = connect(s, begin, connect_condition, ec);
    83   boost::asio::detail::throw_error(ec);
     83  boost::asio::detail::throw_error(ec, "connect");
    8484  return result;
    8585}
     
    101101  boost::system::error_code ec;
    102102  Iterator result = connect(s, begin, end, connect_condition, ec);
    103   boost::asio::detail::throw_error(ec);
     103  boost::asio::detail::throw_error(ec, "connect");
    104104  return result;
    105105}
  • trunk/boost/asio/impl/io_service.ipp

    r69194 r69467  
    119119}
    120120
     121void io_service::notify_fork(boost::asio::io_service::fork_event event)
     122{
     123  service_registry_->notify_fork(event);
     124}
     125
    121126io_service::service::service(boost::asio::io_service& owner)
    122127  : owner_(owner),
     
    126131
    127132io_service::service::~service()
     133{
     134}
     135
     136void io_service::service::fork_service(boost::asio::io_service::fork_event)
    128137{
    129138}
  • trunk/boost/asio/impl/read.hpp

    r69194 r69467  
    6060  boost::system::error_code ec;
    6161  std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
    62   boost::asio::detail::throw_error(ec);
     62  boost::asio::detail::throw_error(ec, "read");
    6363  return bytes_transferred;
    6464}
     
    7878  boost::system::error_code ec;
    7979  std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
    80   boost::asio::detail::throw_error(ec);
     80  boost::asio::detail::throw_error(ec, "read");
    8181  return bytes_transferred;
    8282}
     
    113113  boost::system::error_code ec;
    114114  std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
    115   boost::asio::detail::throw_error(ec);
     115  boost::asio::detail::throw_error(ec, "read");
    116116  return bytes_transferred;
    117117}
     
    133133  boost::system::error_code ec;
    134134  std::size_t bytes_transferred = read(s, b, completion_condition, ec);
    135   boost::asio::detail::throw_error(ec);
     135  boost::asio::detail::throw_error(ec, "read");
    136136  return bytes_transferred;
    137137}
  • trunk/boost/asio/impl/read_at.hpp

    r69194 r69467  
    6464  std::size_t bytes_transferred = read_at(
    6565      d, offset, buffers, transfer_all(), ec);
    66   boost::asio::detail::throw_error(ec);
     66  boost::asio::detail::throw_error(ec, "read_at");
    6767  return bytes_transferred;
    6868}
     
    8585  std::size_t bytes_transferred = read_at(
    8686      d, offset, buffers, completion_condition, ec);
    87   boost::asio::detail::throw_error(ec);
     87  boost::asio::detail::throw_error(ec, "read_at");
    8888  return bytes_transferred;
    8989}
     
    122122  std::size_t bytes_transferred = read_at(
    123123      d, offset, b, transfer_all(), ec);
    124   boost::asio::detail::throw_error(ec);
     124  boost::asio::detail::throw_error(ec, "read_at");
    125125  return bytes_transferred;
    126126}
     
    143143  std::size_t bytes_transferred = read_at(
    144144      d, offset, b, completion_condition, ec);
    145   boost::asio::detail::throw_error(ec);
     145  boost::asio::detail::throw_error(ec, "read_at");
    146146  return bytes_transferred;
    147147}
  • trunk/boost/asio/impl/read_until.hpp

    r69194 r69467  
    4040  boost::system::error_code ec;
    4141  std::size_t bytes_transferred = read_until(s, b, delim, ec);
    42   boost::asio::detail::throw_error(ec);
     42  boost::asio::detail::throw_error(ec, "read_until");
    4343  return bytes_transferred;
    4444}
     
    9696  boost::system::error_code ec;
    9797  std::size_t bytes_transferred = read_until(s, b, delim, ec);
    98   boost::asio::detail::throw_error(ec);
     98  boost::asio::detail::throw_error(ec, "read_until");
    9999  return bytes_transferred;
    100100}
     
    196196  boost::system::error_code ec;
    197197  std::size_t bytes_transferred = read_until(s, b, expr, ec);
    198   boost::asio::detail::throw_error(ec);
     198  boost::asio::detail::throw_error(ec, "read_until");
    199199  return bytes_transferred;
    200200}
     
    316316  boost::system::error_code ec;
    317317  std::size_t bytes_transferred = read_until(s, b, match_condition, ec);
    318   boost::asio::detail::throw_error(ec);
     318  boost::asio::detail::throw_error(ec, "read_until");
    319319  return bytes_transferred;
    320320}
  • trunk/boost/asio/impl/write.hpp

    r69194 r69467  
    5858  boost::system::error_code ec;
    5959  std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
    60   boost::asio::detail::throw_error(ec);
     60  boost::asio::detail::throw_error(ec, "write");
    6161  return bytes_transferred;
    6262}
     
    7676  boost::system::error_code ec;
    7777  std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
    78   boost::asio::detail::throw_error(ec);
     78  boost::asio::detail::throw_error(ec, "write");
    7979  return bytes_transferred;
    8080}
     
    9999  boost::system::error_code ec;
    100100  std::size_t bytes_transferred = write(s, b, transfer_all(), ec);
    101   boost::asio::detail::throw_error(ec);
     101  boost::asio::detail::throw_error(ec, "write");
    102102  return bytes_transferred;
    103103}
     
    119119  boost::system::error_code ec;
    120120  std::size_t bytes_transferred = write(s, b, completion_condition, ec);
    121   boost::asio::detail::throw_error(ec);
     121  boost::asio::detail::throw_error(ec, "write");
    122122  return bytes_transferred;
    123123}
  • trunk/boost/asio/impl/write_at.hpp

    r69194 r69467  
    6262  std::size_t bytes_transferred = write_at(
    6363      d, offset, buffers, transfer_all(), ec);
    64   boost::asio::detail::throw_error(ec);
     64  boost::asio::detail::throw_error(ec, "write_at");
    6565  return bytes_transferred;
    6666}
     
    8383  std::size_t bytes_transferred = write_at(
    8484      d, offset, buffers, completion_condition, ec);
    85   boost::asio::detail::throw_error(ec);
     85  boost::asio::detail::throw_error(ec, "write_at");
    8686  return bytes_transferred;
    8787}
     
    107107  boost::system::error_code ec;
    108108  std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
    109   boost::asio::detail::throw_error(ec);
     109  boost::asio::detail::throw_error(ec, "write_at");
    110110  return bytes_transferred;
    111111}
     
    128128  std::size_t bytes_transferred = write_at(
    129129      d, offset, b, completion_condition, ec);
    130   boost::asio::detail::throw_error(ec);
     130  boost::asio::detail::throw_error(ec, "write_at");
    131131  return bytes_transferred;
    132132}
  • trunk/boost/asio/io_service.hpp

    r69194 r69467  
    6969 * @par Thread Safety
    7070 * @e Distinct @e objects: Safe.@n
    71  * @e Shared @e objects: Safe, with the exception that calling reset() while
    72  * there are unfinished run(), run_one(), poll() or poll_one() calls results in
    73  * undefined behaviour.
     71 * @e Shared @e objects: Safe, with the specific exceptions of the reset() and
     72 * notify_fork() functions. Calling reset() while there are unfinished run(),
     73 * run_one(), poll() or poll_one() calls results in undefined behaviour. The
     74 * notify_fork() function should not be called while any io_service function,
     75 * or any function on an I/O object that is associated with the io_service, is
     76 * being called in another thread.
    7477 *
    7578 * @par Concepts:
     
    496499  wrap(Handler handler);
    497500
     501  /// Fork-related event notifications.
     502  enum fork_event
     503  {
     504    /// Notify the io_service that the process is about to fork.
     505    fork_prepare,
     506
     507    /// Notify the io_service that the process has forked and is the parent.
     508    fork_parent,
     509
     510    /// Notify the io_service that the process has forked and is the child.
     511    fork_child
     512  };
     513
     514  /// Notify the io_service of a fork-related event.
     515  /**
     516   * This function is used to inform the io_service that the process is about
     517   * to fork, or has just forked. This allows the io_service, and the services
     518   * it contains, to perform any necessary housekeeping to ensure correct
     519   * operation following a fork.
     520   *
     521   * This function must not be called while any other io_service function, or
     522   * any function on an I/O object associated with the io_service, is being
     523   * called in another thread. It is, however, safe to call this function from
     524   * within a completion handler, provided no other thread is accessing the
     525   * io_service.
     526   *
     527   * @param event A fork-related event.
     528   *
     529   * @throws boost::system::system_error Thrown on failure. If the notification
     530   * fails the io_service object should no longer be used and should be
     531   * destroyed.
     532   *
     533   * @par Example
     534   * The following code illustrates how to incorporate the notify_fork()
     535   * function:
     536   * @code my_io_service.notify_fork(boost::asio::io_service::fork_prepare);
     537   * if (fork() == 0)
     538   * {
     539   *   // This is the child process.
     540   *   my_io_service.notify_fork(boost::asio::io_service::fork_child);
     541   * }
     542   * else
     543   * {
     544   *   // This is the parent process.
     545   *   my_io_service.notify_fork(boost::asio::io_service::fork_parent);
     546   * } @endcode
     547   *
     548   * @note For each service object @c svc in the io_service set, performs
     549   * <tt>svc->fork_service();</tt>. When processing the fork_prepare event,
     550   * services are visited in reverse order of the beginning of service object
     551   * lifetime. Otherwise, services are visited in order of the beginning of
     552   * service object lifetime.
     553   */
     554  BOOST_ASIO_DECL void notify_fork(boost::asio::io_service::fork_event event);
     555
    498556  /// Obtain the service object corresponding to the given type.
    499557  /**
     
    636694  virtual void shutdown_service() = 0;
    637695
     696  /// Handle notification of a fork-related event to perform any necessary
     697  /// housekeeping.
     698  /**
     699   * This function is not a pure virtual so that services only have to
     700   * implement it if necessary. The default implementation does nothing.
     701   */
     702  BOOST_ASIO_DECL virtual void fork_service(
     703      boost::asio::io_service::fork_event event);
     704
    638705  friend class boost::asio::detail::service_registry;
    639706  struct key
  • trunk/boost/asio/ip/basic_resolver.hpp

    r69194 r69467  
    101101    boost::system::error_code ec;
    102102    iterator i = this->service.resolve(this->implementation, q, ec);
    103     boost::asio::detail::throw_error(ec);
     103    boost::asio::detail::throw_error(ec, "resolve");
    104104    return i;
    105105  }
     
    187187    boost::system::error_code ec;
    188188    iterator i = this->service.resolve(this->implementation, e, ec);
    189     boost::asio::detail::throw_error(ec);
     189    boost::asio::detail::throw_error(ec, "resolve");
    190190    return i;
    191191  }
  • trunk/boost/asio/ip/resolver_service.hpp

    r68086 r69467  
    7878  }
    7979
    80   /// Destroy all user-defined handler objects owned by the service.
    81   void shutdown_service()
    82   {
    83     service_impl_.shutdown_service();
    84   }
    85 
    8680  /// Construct a new resolver implementation.
    8781  void construct(implementation_type& impl)
     
    133127
    134128private:
     129  // Destroy all user-defined handler objects owned by the service.
     130  void shutdown_service()
     131  {
     132    service_impl_.shutdown_service();
     133  }
     134
     135  // Perform any fork-related housekeeping.
     136  void fork_service(boost::asio::io_service::fork_event event)
     137  {
     138    service_impl_.fork_service(event);
     139  }
     140
    135141  // The platform-specific implementation.
    136142  service_impl_type service_impl_;
  • trunk/boost/asio/local/connect_pair.hpp

    r68086 r69467  
    5353  boost::system::error_code ec;
    5454  connect_pair(socket1, socket2, ec);
    55   boost::asio::detail::throw_error(ec);
     55  boost::asio::detail::throw_error(ec, "connect_pair");
    5656}
    5757
  • trunk/boost/asio/posix/basic_descriptor.hpp

    r69194 r69467  
    8989    boost::system::error_code ec;
    9090    this->service.assign(this->implementation, native_descriptor, ec);
    91     boost::asio::detail::throw_error(ec);
     91    boost::asio::detail::throw_error(ec, "assign");
    9292  }
    9393
     
    132132    boost::system::error_code ec;
    133133    this->service.assign(this->implementation, native_descriptor, ec);
    134     boost::asio::detail::throw_error(ec);
     134    boost::asio::detail::throw_error(ec, "assign");
    135135  }
    136136
     
    161161   * boost::asio::error::operation_aborted error.
    162162   *
    163    * @throws boost::system::system_error Thrown on failure.
     163   * @throws boost::system::system_error Thrown on failure. Note that, even if
     164   * the function indicates an error, the underlying descriptor is closed.
    164165   */
    165166  void close()
     
    167168    boost::system::error_code ec;
    168169    this->service.close(this->implementation, ec);
    169     boost::asio::detail::throw_error(ec);
     170    boost::asio::detail::throw_error(ec, "close");
    170171  }
    171172
     
    176177   * boost::asio::error::operation_aborted error.
    177178   *
    178    * @param ec Set to indicate what error occurred, if any.
     179   * @param ec Set to indicate what error occurred, if any. Note that, even if
     180   * the function indicates an error, the underlying descriptor is closed.
    179181   */
    180182  boost::system::error_code close(boost::system::error_code& ec)
     
    233235    boost::system::error_code ec;
    234236    this->service.cancel(this->implementation, ec);
    235     boost::asio::detail::throw_error(ec);
     237    boost::asio::detail::throw_error(ec, "cancel");
    236238  }
    237239
     
    276278    boost::system::error_code ec;
    277279    this->service.io_control(this->implementation, command, ec);
    278     boost::asio::detail::throw_error(ec);
     280    boost::asio::detail::throw_error(ec, "io_control");
    279281  }
    280282
     
    346348    boost::system::error_code ec;
    347349    this->service.non_blocking(this->implementation, mode, ec);
    348     boost::asio::detail::throw_error(ec);
     350    boost::asio::detail::throw_error(ec, "non_blocking");
    349351  }
    350352
     
    406408    boost::system::error_code ec;
    407409    this->service.native_non_blocking(this->implementation, mode, ec);
    408     boost::asio::detail::throw_error(ec);
     410    boost::asio::detail::throw_error(ec, "native_non_blocking");
    409411  }
    410412
  • trunk/boost/asio/posix/basic_stream_descriptor.hpp

    r69194 r69467  
    125125    boost::system::error_code ec;
    126126    std::size_t s = this->service.write_some(this->implementation, buffers, ec);
    127     boost::asio::detail::throw_error(ec);
     127    boost::asio::detail::throw_error(ec, "write_some");
    128128    return s;
    129129  }
     
    232232    boost::system::error_code ec;
    233233    std::size_t s = this->service.read_some(this->implementation, buffers, ec);
    234     boost::asio::detail::throw_error(ec);
     234    boost::asio::detail::throw_error(ec, "read_some");
    235235    return s;
    236236  }
  • trunk/boost/asio/posix/stream_descriptor_service.hpp

    r69194 r69467  
    7979  }
    8080
    81   /// Destroy all user-defined handler objects owned by the service.
    82   void shutdown_service()
    83   {
    84     service_impl_.shutdown_service();
    85   }
    86 
    8781  /// Construct a new stream descriptor implementation.
    8882  void construct(implementation_type& impl)
     
    211205
    212206private:
     207  // Destroy all user-defined handler objects owned by the service.
     208  void shutdown_service()
     209  {
     210    service_impl_.shutdown_service();
     211  }
     212
    213213  // The platform-specific implementation.
    214214  service_impl_type service_impl_;
  • trunk/boost/asio/raw_socket_service.hpp

    r69194 r69467  
    9191  }
    9292
    93   /// Destroy all user-defined handler objects owned by the service.
    94   void shutdown_service()
    95   {
    96     service_impl_.shutdown_service();
    97   }
    98 
    9993  /// Construct a new raw socket implementation.
    10094  void construct(implementation_type& impl)
     
    341335
    342336private:
     337  // Destroy all user-defined handler objects owned by the service.
     338  void shutdown_service()
     339  {
     340    service_impl_.shutdown_service();
     341  }
     342
    343343  // The platform-specific implementation.
    344344  service_impl_type service_impl_;
  • trunk/boost/asio/seq_packet_socket_service.hpp

    r69194 r69467  
    9393  }
    9494
    95   /// Destroy all user-defined handler objects owned by the service.
    96   void shutdown_service()
    97   {
    98     service_impl_.shutdown_service();
    99   }
    100 
    10195  /// Construct a new sequenced packet socket implementation.
    10296  void construct(implementation_type& impl)
     
    308302
    309303private:
     304  // Destroy all user-defined handler objects owned by the service.
     305  void shutdown_service()
     306  {
     307    service_impl_.shutdown_service();
     308  }
     309
    310310  // The platform-specific implementation.
    311311  service_impl_type service_impl_;
  • trunk/boost/asio/serial_port_service.hpp

    r69194 r69467  
    8585  }
    8686
    87   /// Destroy all user-defined handler objects owned by the service.
    88   void shutdown_service()
    89   {
    90     service_impl_.shutdown_service();
    91   }
    92 
    9387  /// Construct a new serial port implementation.
    9488  void construct(implementation_type& impl)
     
    205199
    206200private:
     201  // Destroy all user-defined handler objects owned by the service.
     202  void shutdown_service()
     203  {
     204    service_impl_.shutdown_service();
     205  }
     206
    207207  // The platform-specific implementation.
    208208  service_impl_type service_impl_;
  • trunk/boost/asio/signal_set_service.hpp

    r69198 r69467  
    5555  }
    5656
    57   /// Destroy all user-defined handler objects owned by the service.
    58   void shutdown_service()
    59   {
    60     service_impl_.shutdown_service();
    61   }
    62 
    6357  /// Construct a new signal set implementation.
    6458  void construct(implementation_type& impl)
     
    109103
    110104private:
     105  // Destroy all user-defined handler objects owned by the service.
     106  void shutdown_service()
     107  {
     108    service_impl_.shutdown_service();
     109  }
     110
     111  // Perform any fork-related housekeeping.
     112  void fork_service(boost::asio::io_service::fork_event event)
     113  {
     114    service_impl_.fork_service(event);
     115  }
     116
    111117  // The platform-specific implementation.
    112118  detail::signal_set_service service_impl_;
  • trunk/boost/asio/socket_acceptor_service.hpp

    r69194 r69467  
    9191  }
    9292
    93   /// Destroy all user-defined handler objects owned by the service.
    94   void shutdown_service()
    95   {
    96     service_impl_.shutdown_service();
    97   }
    98 
    9993  /// Construct a new socket acceptor implementation.
    10094  void construct(implementation_type& impl)
     
    247241
    248242private:
     243  // Destroy all user-defined handler objects owned by the service.
     244  void shutdown_service()
     245  {
     246    service_impl_.shutdown_service();
     247  }
     248
    249249  // The platform-specific implementation.
    250250  service_impl_type service_impl_;
  • trunk/boost/asio/ssl/context_service.hpp

    r68086 r69467  
    6060    : boost::asio::detail::service_base<context_service>(io_service),
    6161      service_impl_(boost::asio::use_service<service_impl_type>(io_service))
    62   {
    63   }
    64 
    65   /// Destroy all user-defined handler objects owned by the service.
    66   void shutdown_service()
    6762  {
    6863  }
     
    162157
    163158private:
     159  // Destroy all user-defined handler objects owned by the service.
     160  void shutdown_service()
     161  {
     162  }
     163
    164164  // The service that provides the platform-specific implementation.
    165165  service_impl_type& service_impl_;
  • trunk/boost/asio/ssl/stream_service.hpp

    r68086 r69467  
    6060    : boost::asio::detail::service_base<stream_service>(io_service),
    6161      service_impl_(boost::asio::use_service<service_impl_type>(io_service))
    62   {
    63   }
    64 
    65   /// Destroy all user-defined handler objects owned by the service.
    66   void shutdown_service()
    6762  {
    6863  }
     
    172167
    173168private:
     169  // Destroy all user-defined handler objects owned by the service.
     170  void shutdown_service()
     171  {
     172  }
     173
    174174  // The service that provides the platform-specific implementation.
    175175  service_impl_type& service_impl_;
  • trunk/boost/asio/stream_socket_service.hpp

    r69194 r69467  
    9191  }
    9292
    93   /// Destroy all user-defined handler objects owned by the service.
    94   void shutdown_service()
    95   {
    96     service_impl_.shutdown_service();
    97   }
    98 
    9993  /// Construct a new stream socket implementation.
    10094  void construct(implementation_type& impl)
     
    304298
    305299private:
     300  // Destroy all user-defined handler objects owned by the service.
     301  void shutdown_service()
     302  {
     303    service_impl_.shutdown_service();
     304  }
     305
    306306  // The platform-specific implementation.
    307307  service_impl_type service_impl_;
  • trunk/boost/asio/windows/basic_handle.hpp

    r69194 r69467  
    8585    boost::system::error_code ec;
    8686    this->service.assign(this->implementation, handle, ec);
    87     boost::asio::detail::throw_error(ec);
     87    boost::asio::detail::throw_error(ec, "assign");
    8888  }
    8989
     
    128128    boost::system::error_code ec;
    129129    this->service.assign(this->implementation, handle, ec);
    130     boost::asio::detail::throw_error(ec);
     130    boost::asio::detail::throw_error(ec, "assign");
    131131  }
    132132
     
    163163    boost::system::error_code ec;
    164164    this->service.close(this->implementation, ec);
    165     boost::asio::detail::throw_error(ec);
     165    boost::asio::detail::throw_error(ec, "close");
    166166  }
    167167
     
    213213    boost::system::error_code ec;
    214214    this->service.cancel(this->implementation, ec);
    215     boost::asio::detail::throw_error(ec);
     215    boost::asio::detail::throw_error(ec, "cancel");
    216216  }
    217217
  • trunk/boost/asio/windows/basic_random_access_handle.hpp

    r69194 r69467  
    125125    std::size_t s = this->service.write_some_at(
    126126        this->implementation, offset, buffers, ec);
    127     boost::asio::detail::throw_error(ec);
     127    boost::asio::detail::throw_error(ec, "write_some_at");
    128128    return s;
    129129  }
     
    241241    std::size_t s = this->service.read_some_at(
    242242        this->implementation, offset, buffers, ec);
    243     boost::asio::detail::throw_error(ec);
     243    boost::asio::detail::throw_error(ec, "read_some_at");
    244244    return s;
    245245  }
  • trunk/boost/asio/windows/basic_stream_handle.hpp

    r69194 r69467  
    122122    boost::system::error_code ec;
    123123    std::size_t s = this->service.write_some(this->implementation, buffers, ec);
    124     boost::asio::detail::throw_error(ec);
     124    boost::asio::detail::throw_error(ec, "write_some");
    125125    return s;
    126126  }
     
    229229    boost::system::error_code ec;
    230230    std::size_t s = this->service.read_some(this->implementation, buffers, ec);
    231     boost::asio::detail::throw_error(ec);
     231    boost::asio::detail::throw_error(ec, "read_some");
    232232    return s;
    233233  }
  • trunk/boost/asio/windows/random_access_handle_service.hpp

    r69194 r69467  
    8080      service_impl_(io_service)
    8181  {
    82   }
    83 
    84   /// Destroy all user-defined handler objects owned by the service.
    85   void shutdown_service()
    86   {
    87     service_impl_.shutdown_service();
    8882  }
    8983
     
    172166
    173167private:
     168  // Destroy all user-defined handler objects owned by the service.
     169  void shutdown_service()
     170  {
     171    service_impl_.shutdown_service();
     172  }
     173
    174174  // The platform-specific implementation.
    175175  service_impl_type service_impl_;
  • trunk/boost/asio/windows/stream_handle_service.hpp

    r69194 r69467  
    7777      service_impl_(io_service)
    7878  {
    79   }
    80 
    81   /// Destroy all user-defined handler objects owned by the service.
    82   void shutdown_service()
    83   {
    84     service_impl_.shutdown_service();
    8579  }
    8680
     
    169163
    170164private:
     165  // Destroy all user-defined handler objects owned by the service.
     166  void shutdown_service()
     167  {
     168    service_impl_.shutdown_service();
     169  }
     170
    171171  // The platform-specific implementation.
    172172  service_impl_type service_impl_;
  • trunk/libs/asio/doc/Jamfile.v2

    r68086 r69467  
    2626  ;
    2727
    28 local example-names = allocation buffers chat echo http/client http/server
     28local example-names = allocation buffers chat echo fork http/client http/server
    2929  http/server2 http/server3 http/server4 icmp invocation iostreams local
    3030  multicast nonblocking porthopper serialization services socks4 ssl timeouts
  • trunk/libs/asio/doc/examples.qbk

    r69198 r69467  
    5252* [@boost_asio/example/echo/blocking_udp_echo_client.cpp]
    5353* [@boost_asio/example/echo/blocking_udp_echo_server.cpp]
     54
     55
     56[heading Fork]
     57
     58These POSIX-specific examples show how to use Boost.Asio in conjunction with the
     59`fork()` system call. The first example illustrates the steps required to start
     60a daemon process:
     61
     62* [@boost_asio/example/fork/daemon.cpp]
     63
     64The second example demonstrates how it is possible to fork a process from
     65within a completion handler.
     66
     67* [@boost_asio/example/fork/process_per_connection.cpp]
    5468
    5569
  • trunk/libs/asio/example/chat/chat_client.cpp

    r69194 r69467  
    1414#include <boost/bind.hpp>
    1515#include <boost/asio.hpp>
    16 #include <boost/thread.hpp>
     16#include <boost/thread/thread.hpp>
    1717#include "chat_message.hpp"
    1818
  • trunk/libs/asio/example/echo/blocking_tcp_echo_server.cpp

    r68086 r69467  
    1414#include <boost/smart_ptr.hpp>
    1515#include <boost/asio.hpp>
    16 #include <boost/thread.hpp>
     16#include <boost/thread/thread.hpp>
    1717
    1818using boost::asio::ip::tcp;
  • trunk/libs/asio/example/http/server2/io_service_pool.cpp

    r68086 r69467  
    1111#include "server.hpp"
    1212#include <stdexcept>
    13 #include <boost/thread.hpp>
     13#include <boost/thread/thread.hpp>
    1414#include <boost/bind.hpp>
    1515#include <boost/shared_ptr.hpp>
  • trunk/libs/asio/example/http/server3/server.cpp

    r68086 r69467  
    1010
    1111#include "server.hpp"
    12 #include <boost/thread.hpp>
     12#include <boost/thread/thread.hpp>
    1313#include <boost/bind.hpp>
    1414#include <boost/shared_ptr.hpp>
  • trunk/libs/asio/example/local/connect_pair.cpp

    r68086 r69467  
    1313#include <cctype>
    1414#include <boost/asio.hpp>
    15 #include <boost/thread.hpp>
     15#include <boost/thread/thread.hpp>
    1616#include <boost/array.hpp>
    1717#include <boost/bind.hpp>
  • trunk/libs/asio/example/services/logger_service.hpp

    r69194 r69467  
    1313
    1414#include <boost/asio.hpp>
    15 #include <boost/thread.hpp>
     15#include <boost/thread/thread.hpp>
    1616#include <boost/bind.hpp>
    1717#include <boost/date_time/posix_time/posix_time.hpp>
  • trunk/libs/asio/example/timeouts/async_tcp_client.cpp

    r68086 r69467  
    111111  {
    112112    stopped_ = true;
    113     socket_.close();
     113    boost::system::error_code ignored_ec;
     114    socket_.close(ignored_ec);
    114115    deadline_.cancel();
    115116    heartbeat_timer_.cancel();
  • trunk/libs/asio/example/timeouts/blocking_tcp_client.cpp

    r69194 r69467  
    179179      // asynchronous operations are cancelled. This allows the blocked
    180180      // connect(), read_line() or write_line() functions to return.
    181       socket_.close();
     181      boost::system::error_code ignored_ec;
     182      socket_.close(ignored_ec);
    182183
    183184      // There is no longer an active deadline. The expiry is set to positive
  • trunk/libs/asio/example/timeouts/server.cpp

    r68086 r69467  
    178178    channel_.leave(shared_from_this());
    179179
    180     socket_.close();
     180    boost::system::error_code ignored_ec;
     181    socket_.close(ignored_ec);
    181182    input_deadline_.cancel();
    182183    non_empty_output_queue_.cancel();
  • trunk/libs/asio/example/tutorial/timer5/timer.cpp

    r68086 r69467  
    1111#include <iostream>
    1212#include <boost/asio.hpp>
    13 #include <boost/thread.hpp>
     13#include <boost/thread/thread.hpp>
    1414#include <boost/bind.hpp>
    1515#include <boost/date_time/posix_time/posix_time.hpp>
  • trunk/libs/asio/test/deadline_timer.cpp

    r69194 r69467  
    1717#include <boost/asio/deadline_timer.hpp>
    1818
    19 #include <boost/thread.hpp>
     19#include <boost/thread/thread.hpp>
    2020#include <boost/bind.hpp>
    2121#include <boost/asio/io_service.hpp>
  • trunk/libs/asio/test/io_service.cpp

    r69194 r69467  
    1818
    1919#include <sstream>
    20 #include <boost/thread.hpp>
     20#include <boost/thread/thread.hpp>
    2121#include <boost/bind.hpp>
    2222#include <boost/asio/deadline_timer.hpp>
  • trunk/libs/asio/test/ip/tcp.cpp

    r69194 r69467  
    2727#include <boost/asio/write.hpp>
    2828#include "../unit_test.hpp"
     29#include "../archetypes/gettable_socket_option.hpp"
    2930#include "../archetypes/io_control_command.hpp"
     31#include "../archetypes/settable_socket_option.hpp"
    3032
    3133//------------------------------------------------------------------------------
     
    157159    socket_base::message_flags in_flags = 0;
    158160    socket_base::keep_alive socket_option;
     161    archetypes::settable_socket_option<void> settable_socket_option1;
     162    archetypes::settable_socket_option<int> settable_socket_option2;
     163    archetypes::settable_socket_option<double> settable_socket_option3;
     164    archetypes::gettable_socket_option<void> gettable_socket_option1;
     165    archetypes::gettable_socket_option<int> gettable_socket_option2;
     166    archetypes::gettable_socket_option<double> gettable_socket_option3;
    159167    archetypes::io_control_command io_control_command;
    160168    boost::system::error_code ec;
     
    234242    socket1.async_connect(ip::tcp::endpoint(ip::tcp::v6(), 0), connect_handler);
    235243
    236     socket1.set_option(socket_option);
    237     socket1.set_option(socket_option, ec);
    238 
    239     socket1.get_option(socket_option);
    240     socket1.get_option(socket_option, ec);
     244    socket1.set_option(settable_socket_option1);
     245    socket1.set_option(settable_socket_option1, ec);
     246    socket1.set_option(settable_socket_option2);
     247    socket1.set_option(settable_socket_option2, ec);
     248    socket1.set_option(settable_socket_option3);
     249    socket1.set_option(settable_socket_option3, ec);
     250
     251    socket1.get_option(gettable_socket_option1);
     252    socket1.get_option(gettable_socket_option1, ec);
     253    socket1.get_option(gettable_socket_option2);
     254    socket1.get_option(gettable_socket_option2, ec);
     255    socket1.get_option(gettable_socket_option3);
     256    socket1.get_option(gettable_socket_option3, ec);
    241257
    242258    socket1.io_control(io_control_command);
  • trunk/libs/asio/test/ip/udp.cpp

    r69194 r69467  
    2222#include <boost/asio/placeholders.hpp>
    2323#include "../unit_test.hpp"
     24#include "../archetypes/gettable_socket_option.hpp"
    2425#include "../archetypes/io_control_command.hpp"
     26#include "../archetypes/settable_socket_option.hpp"
    2527
    2628//------------------------------------------------------------------------------
     
    5658    const char const_char_buffer[128] = "";
    5759    socket_base::message_flags in_flags = 0;
    58     socket_base::keep_alive socket_option;
     60    archetypes::settable_socket_option<void> settable_socket_option1;
     61    archetypes::settable_socket_option<int> settable_socket_option2;
     62    archetypes::settable_socket_option<double> settable_socket_option3;
     63    archetypes::gettable_socket_option<void> gettable_socket_option1;
     64    archetypes::gettable_socket_option<int> gettable_socket_option2;
     65    archetypes::gettable_socket_option<double> gettable_socket_option3;
    5966    archetypes::io_control_command io_control_command;
    6067    boost::system::error_code ec;
     
    134141    socket1.async_connect(ip::udp::endpoint(ip::udp::v6(), 0), connect_handler);
    135142
    136     socket1.set_option(socket_option);
    137     socket1.set_option(socket_option, ec);
    138 
    139     socket1.get_option(socket_option);
    140     socket1.get_option(socket_option, ec);
     143    socket1.set_option(settable_socket_option1);
     144    socket1.set_option(settable_socket_option1, ec);
     145    socket1.set_option(settable_socket_option2);
     146    socket1.set_option(settable_socket_option2, ec);
     147    socket1.set_option(settable_socket_option3);
     148    socket1.set_option(settable_socket_option3, ec);
     149
     150    socket1.get_option(gettable_socket_option1);
     151    socket1.get_option(gettable_socket_option1, ec);
     152    socket1.get_option(gettable_socket_option2);
     153    socket1.get_option(gettable_socket_option2, ec);
     154    socket1.get_option(gettable_socket_option3);
     155    socket1.get_option(gettable_socket_option3, ec);
    141156
    142157    socket1.io_control(io_control_command);
  • trunk/libs/asio/test/strand.cpp

    r68086 r69467  
    1818
    1919#include <sstream>
    20 #include <boost/thread.hpp>
     20#include <boost/thread/thread.hpp>
    2121#include <boost/bind.hpp>
    2222#include <boost/asio/deadline_timer.hpp>
Note: See TracChangeset for help on using the changeset viewer.