Browse Source

[3478] DHCPv6 server doesn't log an error of select() when signal received.

Marcin Siodelski 10 years ago
parent
commit
d78e336733

+ 7 - 0
src/bin/dhcp6/dhcp6_srv.cc

@@ -242,6 +242,13 @@ bool Dhcpv6Srv::run() {
 
         try {
             query = receivePacket(timeout);
+
+        } catch (const SignalInterruptOnSelect) {
+            // Packet reception interrupted because a signal has been received.
+            // This is not an error because we might have received a SIGTERM,
+            // SIGINT or SIGHUP which are handled by the server. For signals
+            // that are not handled by the server we rely on the default
+            // behavior of the system, but there is nothing we should log here.
         } catch (const std::exception& e) {
             LOG_ERROR(dhcp6_logger, DHCP6_PACKET_RECEIVE_FAIL).arg(e.what());
         }

+ 14 - 0
src/bin/dhcp6/tests/dhcp6_process_tests.sh.in

@@ -193,6 +193,13 @@ dynamic_reconfiguration_test() {
         clean_exit 1
     fi
 
+    # When the server receives a signal the call to select() function is
+    # interrupted. This should not be logged as an error.
+    get_log_messages "DHCP6_PACKET_RECEIVE_FAIL"
+    assert_eq 0 ${_GET_LOG_MESSAGES} \
+        "Expected get_log_messages DHCP6_PACKET_RECEIVE_FAIL return %d, \
+returned %d."
+
     # All ok. Shut down Kea and exit.
     test_finish 0
 }
@@ -255,6 +262,13 @@ shutdown_test() {
     assert_eq 1 ${_WAIT_FOR_SERVER_DOWN} \
         "Expected wait_for_server_down return %d, returned %d"
 
+    # When the server receives a signal the call to select() function is
+    # interrupted. This should not be logged as an error.
+    get_log_messages "DHCP6_PACKET_RECEIVE_FAIL"
+    assert_eq 0 ${_GET_LOG_MESSAGES} \
+        "Expected get_log_messages DHCP6_PACKET_RECEIVE_FAIL return %d, \
+returned %d."
+
     test_finish 0
 }
 

+ 13 - 1
src/lib/dhcp/iface_mgr.cc

@@ -1053,8 +1053,20 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
     if (result == 0) {
         // nothing received and timeout has been reached
         return (Pkt6Ptr()); // NULL
+
     } else if (result < 0) {
-        isc_throw(SocketReadError, strerror(errno));
+        // In most cases we would like to know whether select() returned
+        // an error because of a signal being received  or for some other
+        // reasaon. This is because DHCP servers use signals to trigger
+        // certain actions, like reconfiguration or graceful shutdown.
+        // By cacthing a dedicated exception the caller will know if the
+        // error returned by the function is due to the reception of the
+        // signal or for some other reason.
+        if (errno == EINTR) {
+            isc_throw(SignalInterruptOnSelect, strerror(errno));
+        } else {
+            isc_throw(SocketReadError, strerror(errno));
+        }
     }
 
     // Let's find out which socket has the data