Browse Source

Add EINTR and EAGAIN judge for accept (#1438)

* Add EINTR and EAGAIN judge for accept

* Add EINTR signal tests

* Cancel win32 and win64 compile on signal unittest

Co-authored-by: yukun.yu <[email protected]>
yukun 3 years ago
parent
commit
227d2c2050
2 changed files with 41 additions and 0 deletions
  1. 2 0
      httplib.h
  2. 39 0
      test/test.cc

+ 2 - 0
httplib.h

@@ -5507,6 +5507,8 @@ inline bool Server::listen_internal() {
           // Try to accept new connections after a short sleep.
           std::this_thread::sleep_for(std::chrono::milliseconds(1));
           continue;
+        } else if (errno == EINTR || errno == EAGAIN) {
+          continue;
         }
         if (svr_sock_ != INVALID_SOCKET) {
           detail::close_socket(svr_sock_);

+ 39 - 0
test/test.cc

@@ -1,4 +1,5 @@
 #include <httplib.h>
+#include <signal.h>
 
 #include <gtest/gtest.h>
 
@@ -943,6 +944,44 @@ TEST(UrlWithSpace, Redirect_Online) {
 
 #endif
 
+#if !defined(_WIN32) && !defined(_WIN64)
+TEST(ReceiveSignals, Signal) {
+  auto setupSignalHandlers = []() {
+    struct sigaction act;
+
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = SA_SIGINFO;
+    act.sa_sigaction = [](int sig, siginfo_t *, void *) {
+      switch (sig) {
+      case SIGINT:
+      default: break;
+      }
+    };
+    ::sigaction(SIGINT, &act, nullptr);
+  };
+
+  Server svr;
+  int port = 0;
+  auto thread = std::thread([&]() {
+    setupSignalHandlers();
+    port = svr.bind_to_any_port("localhost");
+    svr.listen_after_bind();
+  });
+
+  while (!svr.is_running()) {
+    std::this_thread::sleep_for(std::chrono::milliseconds(1));
+  }
+
+  ASSERT_TRUE(svr.is_running());
+  pthread_kill(thread.native_handle(), SIGINT);
+  std::this_thread::sleep_for(std::chrono::milliseconds(100));
+  ASSERT_TRUE(svr.is_running());
+  svr.stop();
+  thread.join();
+  ASSERT_FALSE(svr.is_running());
+}
+#endif
+
 TEST(RedirectToDifferentPort, Redirect) {
   Server svr1;
   svr1.Get("/1", [&](const Request & /*req*/, Response &res) {