ShutdownSocketSet.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <atomic>
  18. #include <cstdlib>
  19. #include <memory>
  20. #include <boost/noncopyable.hpp>
  21. #include <folly/File.h>
  22. namespace folly {
  23. /**
  24. * Set of sockets that allows immediate, take-no-prisoners abort.
  25. */
  26. class ShutdownSocketSet : private boost::noncopyable {
  27. public:
  28. /**
  29. * Create a socket set that can handle file descriptors < maxFd.
  30. * The default value (256Ki) is high enough for just about all
  31. * applications, even if you increased the number of file descriptors
  32. * on your system.
  33. */
  34. explicit ShutdownSocketSet(int maxFd = 1 << 18);
  35. /**
  36. * Add an already open socket to the list of sockets managed by
  37. * ShutdownSocketSet. You MUST close the socket by calling
  38. * ShutdownSocketSet::close (which will, as a side effect, also handle EINTR
  39. * properly) and not by calling close() on the file descriptor.
  40. */
  41. void add(int fd);
  42. /**
  43. * Remove a socket from the list of sockets managed by ShutdownSocketSet.
  44. * Note that remove() might block! (which we lamely implement by
  45. * sleep()-ing) in the extremely rare case that the fd is currently
  46. * being shutdown().
  47. */
  48. void remove(int fd);
  49. /**
  50. * Close a socket managed by ShutdownSocketSet. Returns the same return code
  51. * as ::close() (and sets errno accordingly).
  52. */
  53. int close(int fd);
  54. /**
  55. * Shut down a socket. If abortive is true, we perform an abortive
  56. * shutdown (send RST rather than FIN). Note that we might still end up
  57. * sending FIN due to the rather interesting implementation.
  58. *
  59. * This is async-signal-safe and ignores errors. Obviously, subsequent
  60. * read() and write() operations to the socket will fail. During normal
  61. * operation, just call ::shutdown() on the socket.
  62. */
  63. void shutdown(int fd, bool abortive = false);
  64. /**
  65. * Immediate shutdown of all connections. This is a hard-hitting hammer;
  66. * all reads and writes will return errors and no new connections will
  67. * be accepted.
  68. *
  69. * To be used only in dire situations. We're using it from the failure
  70. * signal handler to close all connections quickly, even though the server
  71. * might take multiple seconds to finish crashing.
  72. *
  73. * The optional bool parameter indicates whether to set the active
  74. * connections in to not linger. The effect of that includes RST packets
  75. * being immediately sent to clients which will result
  76. * in errors (and not normal EOF) on the client side. This also causes
  77. * the local (ip, tcp port number) tuple to be reusable immediately, instead
  78. * of having to wait the standard amount of time. For full details see
  79. * the `shutdown` method of `ShutdownSocketSet` (incl. notes about the
  80. * `abortive` parameter).
  81. *
  82. * This is async-signal-safe and ignores errors.
  83. */
  84. void shutdownAll(bool abortive = false);
  85. private:
  86. void doShutdown(int fd, bool abortive);
  87. // State transitions:
  88. // add():
  89. // FREE -> IN_USE
  90. //
  91. // close():
  92. // IN_USE -> (::close()) -> FREE
  93. // SHUT_DOWN -> (::close()) -> FREE
  94. // IN_SHUTDOWN -> MUST_CLOSE
  95. // (If the socket is currently being shut down, we must defer the
  96. // ::close() until the shutdown completes)
  97. //
  98. // shutdown():
  99. // IN_USE -> IN_SHUTDOWN
  100. // (::shutdown())
  101. // IN_SHUTDOWN -> SHUT_DOWN
  102. // MUST_CLOSE -> (::close()) -> FREE
  103. //
  104. // State atomic operation memory orders:
  105. // All atomic operations on per-socket states use std::memory_order_relaxed
  106. // because there is no associated per-socket data guarded by the state and
  107. // the states for different sockets are unrelated. If there were associated
  108. // per-socket data, acquire and release orders would be desired; and if the
  109. // states for different sockets were related, it could be that sequential
  110. // consistent orders would be desired.
  111. enum State : uint8_t {
  112. FREE = 0,
  113. IN_USE,
  114. IN_SHUTDOWN,
  115. SHUT_DOWN,
  116. MUST_CLOSE,
  117. };
  118. struct Free {
  119. template <class T>
  120. void operator()(T* ptr) const {
  121. ::free(ptr);
  122. }
  123. };
  124. const int maxFd_;
  125. std::unique_ptr<std::atomic<uint8_t>[], Free> data_;
  126. folly::File nullFile_;
  127. };
  128. } // namespace folly