2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <boost/noncopyable.hpp>
25 #include <folly/File.h>
30 * Set of sockets that allows immediate, take-no-prisoners abort.
32 class ShutdownSocketSet : private boost::noncopyable {
35 * Create a socket set that can handle file descriptors < maxFd.
36 * The default value (256Ki) is high enough for just about all
37 * applications, even if you increased the number of file descriptors
40 explicit ShutdownSocketSet(int maxFd = 1 << 18);
42 // Singleton instance used by all thrift servers.
43 // May return nullptr on startup/shutdown.
44 static std::shared_ptr<ShutdownSocketSet> getInstance();
47 * Add an already open socket to the list of sockets managed by
48 * ShutdownSocketSet. You MUST close the socket by calling
49 * ShutdownSocketSet::close (which will, as a side effect, also handle EINTR
50 * properly) and not by calling close() on the file descriptor.
55 * Remove a socket from the list of sockets managed by ShutdownSocketSet.
56 * Note that remove() might block! (which we lamely implement by
57 * sleep()-ing) in the extremely rare case that the fd is currently
63 * Close a socket managed by ShutdownSocketSet. Returns the same return code
64 * as ::close() (and sets errno accordingly).
69 * Shut down a socket. If abortive is true, we perform an abortive
70 * shutdown (send RST rather than FIN). Note that we might still end up
71 * sending FIN due to the rather interesting implementation.
73 * This is async-signal-safe and ignores errors. Obviously, subsequent
74 * read() and write() operations to the socket will fail. During normal
75 * operation, just call ::shutdown() on the socket.
77 void shutdown(int fd, bool abortive=false);
80 * Immediate shutdown of all connections. This is a hard-hitting hammer;
81 * all reads and writes will return errors and no new connections will
84 * To be used only in dire situations. We're using it from the failure
85 * signal handler to close all connections quickly, even though the server
86 * might take multiple seconds to finish crashing.
88 * The optional bool parameter indicates whether to set the active
89 * connections in to not linger. The effect of that includes RST packets
90 * being immediately sent to clients which will result
91 * in errors (and not normal EOF) on the client side. This also causes
92 * the local (ip, tcp port number) tuple to be reusable immediately, instead
93 * of having to wait the standard amount of time. For full details see
94 * the `shutdown` method of `ShutdownSocketSet` (incl. notes about the
95 * `abortive` parameter).
97 * This is async-signal-safe and ignores errors.
99 void shutdownAll(bool abortive=false);
102 void doShutdown(int fd, bool abortive);
104 // State transitions:
109 // IN_USE -> (::close()) -> FREE
110 // SHUT_DOWN -> (::close()) -> FREE
111 // IN_SHUTDOWN -> MUST_CLOSE
112 // (If the socket is currently being shut down, we must defer the
113 // ::close() until the shutdown completes)
116 // IN_USE -> IN_SHUTDOWN
118 // IN_SHUTDOWN -> SHUT_DOWN
119 // MUST_CLOSE -> (::close()) -> FREE
121 // State atomic operation memory orders:
122 // All atomic operations on per-socket states use std::memory_order_relaxed
123 // because there is no associated per-socket data guarded by the state and
124 // the states for different sockets are unrelated. If there were associated
125 // per-socket data, acquire and release orders would be desired; and if the
126 // states for different sockets were related, it could be that sequential
127 // consistent orders would be desired.
128 enum State : uint8_t {
138 void operator()(T* ptr) const {
144 std::unique_ptr<std::atomic<uint8_t>[], Free> data_;
145 folly::File nullFile_;