grpc 1.55.0 → 1.55.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Makefile +4 -2
- data/src/core/ext/filters/client_channel/client_channel.cc +4 -6
- data/src/core/ext/filters/client_channel/client_channel.h +2 -0
- data/src/core/ext/transport/chttp2/transport/hpack_parse_result.cc +176 -0
- data/src/core/ext/transport/chttp2/transport/hpack_parse_result.h +325 -0
- data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +567 -543
- data/src/core/ext/transport/chttp2/transport/hpack_parser.h +150 -9
- data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +46 -32
- data/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +18 -5
- data/src/core/ext/transport/chttp2/transport/parsing.cc +12 -12
- data/src/core/lib/backoff/random_early_detection.h +5 -0
- data/src/core/lib/event_engine/posix_engine/posix_engine.cc +30 -17
- data/src/core/lib/event_engine/posix_engine/posix_engine.h +1 -0
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc +29 -0
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener.h +3 -0
- data/src/core/lib/iomgr/tcp_server_posix.cc +39 -14
- data/src/core/lib/iomgr/tcp_server_utils_posix.h +12 -0
- data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +21 -0
- data/src/core/lib/surface/validate_metadata.cc +37 -22
- data/src/core/lib/surface/validate_metadata.h +13 -3
- data/src/ruby/lib/grpc/version.rb +1 -1
- metadata +5 -3
@@ -23,7 +23,9 @@
|
|
23
23
|
#include <sys/socket.h> // IWYU pragma: keep
|
24
24
|
#include <unistd.h> // IWYU pragma: keep
|
25
25
|
|
26
|
+
#include <atomic>
|
26
27
|
#include <string>
|
28
|
+
#include <tuple>
|
27
29
|
#include <utility>
|
28
30
|
|
29
31
|
#include "absl/functional/any_invocable.h"
|
@@ -41,6 +43,7 @@
|
|
41
43
|
#include "src/core/lib/event_engine/posix_engine/tcp_socket_utils.h"
|
42
44
|
#include "src/core/lib/event_engine/tcp_socket_utils.h"
|
43
45
|
#include "src/core/lib/gprpp/status_helper.h"
|
46
|
+
#include "src/core/lib/gprpp/time.h"
|
44
47
|
#include "src/core/lib/iomgr/socket_mutator.h"
|
45
48
|
|
46
49
|
namespace grpc_event_engine {
|
@@ -136,6 +139,32 @@ void PosixEngineListenerImpl::AsyncConnectionAcceptor::NotifyOnAccept(
|
|
136
139
|
switch (errno) {
|
137
140
|
case EINTR:
|
138
141
|
continue;
|
142
|
+
case EMFILE:
|
143
|
+
// When the process runs out of fds, accept4() returns EMFILE. When
|
144
|
+
// this happens, the connection is left in the accept queue until
|
145
|
+
// either a read event triggers the on_read callback, or time has
|
146
|
+
// passed and the accept should be re-tried regardless. This callback
|
147
|
+
// is not cancelled, so a spurious wakeup may occur even when there's
|
148
|
+
// nothing to accept. This is not a performant code path, but if an fd
|
149
|
+
// limit has been reached, the system is likely in an unhappy state
|
150
|
+
// regardless.
|
151
|
+
GRPC_LOG_EVERY_N_SEC(1, GPR_ERROR, "%s",
|
152
|
+
"File descriptor limit reached. Retrying.");
|
153
|
+
handle_->NotifyOnRead(notify_on_accept_);
|
154
|
+
// Do not schedule another timer if one is already armed.
|
155
|
+
if (retry_timer_armed_.exchange(true)) return;
|
156
|
+
// Hold a ref while the retry timer is waiting, to prevent listener
|
157
|
+
// destruction and the races that would ensue.
|
158
|
+
Ref();
|
159
|
+
std::ignore =
|
160
|
+
engine_->RunAfter(grpc_core::Duration::Seconds(1), [this]() {
|
161
|
+
retry_timer_armed_.store(false);
|
162
|
+
if (!handle_->IsHandleShutdown()) {
|
163
|
+
handle_->SetReadable();
|
164
|
+
}
|
165
|
+
Unref();
|
166
|
+
});
|
167
|
+
return;
|
139
168
|
case EAGAIN:
|
140
169
|
case ECONNABORTED:
|
141
170
|
handle_->NotifyOnRead(notify_on_accept_);
|
@@ -121,6 +121,9 @@ class PosixEngineListenerImpl
|
|
121
121
|
ListenerSocketsContainer::ListenerSocket socket_;
|
122
122
|
EventHandle* handle_;
|
123
123
|
PosixEngineClosure* notify_on_accept_;
|
124
|
+
// Tracks the status of a backup timer to retry accept4 calls after file
|
125
|
+
// descriptor exhaustion.
|
126
|
+
std::atomic<bool> retry_timer_armed_{false};
|
124
127
|
};
|
125
128
|
class ListenerAsyncAcceptors : public ListenerSocketsContainer {
|
126
129
|
public:
|
@@ -16,13 +16,17 @@
|
|
16
16
|
//
|
17
17
|
//
|
18
18
|
|
19
|
+
#include <grpc/support/port_platform.h>
|
20
|
+
|
21
|
+
#include <utility>
|
22
|
+
|
23
|
+
#include <grpc/support/atm.h>
|
24
|
+
|
19
25
|
// FIXME: "posix" files shouldn't be depending on _GNU_SOURCE
|
20
26
|
#ifndef _GNU_SOURCE
|
21
27
|
#define _GNU_SOURCE
|
22
28
|
#endif
|
23
29
|
|
24
|
-
#include <grpc/support/port_platform.h>
|
25
|
-
|
26
30
|
#include "src/core/lib/iomgr/port.h"
|
27
31
|
|
28
32
|
#ifdef GRPC_POSIX_SOCKET_TCP_SERVER
|
@@ -45,6 +49,7 @@
|
|
45
49
|
|
46
50
|
#include <grpc/byte_buffer.h>
|
47
51
|
#include <grpc/event_engine/endpoint_config.h>
|
52
|
+
#include <grpc/event_engine/event_engine.h>
|
48
53
|
#include <grpc/support/alloc.h>
|
49
54
|
#include <grpc/support/log.h>
|
50
55
|
#include <grpc/support/sync.h>
|
@@ -75,6 +80,8 @@
|
|
75
80
|
#include "src/core/lib/transport/error_utils.h"
|
76
81
|
|
77
82
|
static std::atomic<int64_t> num_dropped_connections{0};
|
83
|
+
static constexpr grpc_core::Duration kRetryAcceptWaitTime{
|
84
|
+
grpc_core::Duration::Seconds(1)};
|
78
85
|
|
79
86
|
using ::grpc_event_engine::experimental::EndpointConfig;
|
80
87
|
using ::grpc_event_engine::experimental::EventEngine;
|
@@ -339,22 +346,38 @@ static void on_read(void* arg, grpc_error_handle err) {
|
|
339
346
|
if (fd < 0) {
|
340
347
|
if (errno == EINTR) {
|
341
348
|
continue;
|
342
|
-
}
|
343
|
-
|
349
|
+
}
|
350
|
+
// When the process runs out of fds, accept4() returns EMFILE. When this
|
351
|
+
// happens, the connection is left in the accept queue until either a
|
352
|
+
// read event triggers the on_read callback, or time has passed and the
|
353
|
+
// accept should be re-tried regardless. This callback is not cancelled,
|
354
|
+
// so a spurious wakeup may occur even when there's nothing to accept.
|
355
|
+
// This is not a performant code path, but if an fd limit has been
|
356
|
+
// reached, the system is likely in an unhappy state regardless.
|
357
|
+
if (errno == EMFILE) {
|
358
|
+
GRPC_LOG_EVERY_N_SEC(1, GPR_ERROR, "%s",
|
359
|
+
"File descriptor limit reached. Retrying.");
|
360
|
+
grpc_fd_notify_on_read(sp->emfd, &sp->read_closure);
|
361
|
+
if (gpr_atm_full_xchg(&sp->retry_timer_armed, true)) return;
|
362
|
+
grpc_timer_init(&sp->retry_timer,
|
363
|
+
grpc_core::Timestamp::Now() + kRetryAcceptWaitTime,
|
364
|
+
&sp->retry_closure);
|
365
|
+
return;
|
366
|
+
}
|
367
|
+
if (errno == EAGAIN || errno == ECONNABORTED || errno == EWOULDBLOCK) {
|
344
368
|
grpc_fd_notify_on_read(sp->emfd, &sp->read_closure);
|
345
369
|
return;
|
370
|
+
}
|
371
|
+
gpr_mu_lock(&sp->server->mu);
|
372
|
+
if (!sp->server->shutdown_listeners) {
|
373
|
+
gpr_log(GPR_ERROR, "Failed accept4: %s",
|
374
|
+
grpc_core::StrError(errno).c_str());
|
346
375
|
} else {
|
347
|
-
|
348
|
-
|
349
|
-
gpr_log(GPR_ERROR, "Failed accept4: %s",
|
350
|
-
grpc_core::StrError(errno).c_str());
|
351
|
-
} else {
|
352
|
-
// if we have shutdown listeners, accept4 could fail, and we
|
353
|
-
// needn't notify users
|
354
|
-
}
|
355
|
-
gpr_mu_unlock(&sp->server->mu);
|
356
|
-
goto error;
|
376
|
+
// if we have shutdown listeners, accept4 could fail, and we
|
377
|
+
// needn't notify users
|
357
378
|
}
|
379
|
+
gpr_mu_unlock(&sp->server->mu);
|
380
|
+
goto error;
|
358
381
|
}
|
359
382
|
|
360
383
|
if (sp->server->memory_quota->IsMemoryPressureHigh()) {
|
@@ -547,6 +570,7 @@ static grpc_error_handle clone_port(grpc_tcp_listener* listener,
|
|
547
570
|
sp->port_index = listener->port_index;
|
548
571
|
sp->fd_index = listener->fd_index + count - i;
|
549
572
|
GPR_ASSERT(sp->emfd);
|
573
|
+
grpc_tcp_server_listener_initialize_retry_timer(sp);
|
550
574
|
while (listener->server->tail->next != nullptr) {
|
551
575
|
listener->server->tail = listener->server->tail->next;
|
552
576
|
}
|
@@ -780,6 +804,7 @@ static void tcp_server_shutdown_listeners(grpc_tcp_server* s) {
|
|
780
804
|
if (s->active_ports) {
|
781
805
|
grpc_tcp_listener* sp;
|
782
806
|
for (sp = s->head; sp; sp = sp->next) {
|
807
|
+
grpc_timer_cancel(&sp->retry_timer);
|
783
808
|
grpc_fd_shutdown(sp->emfd, GRPC_ERROR_CREATE("Server shutdown"));
|
784
809
|
}
|
785
810
|
}
|
@@ -30,6 +30,7 @@
|
|
30
30
|
#include "src/core/lib/iomgr/resolve_address.h"
|
31
31
|
#include "src/core/lib/iomgr/socket_utils_posix.h"
|
32
32
|
#include "src/core/lib/iomgr/tcp_server.h"
|
33
|
+
#include "src/core/lib/iomgr/timer.h"
|
33
34
|
#include "src/core/lib/resource_quota/memory_quota.h"
|
34
35
|
|
35
36
|
// one listening port
|
@@ -52,6 +53,11 @@ typedef struct grpc_tcp_listener {
|
|
52
53
|
// identified while iterating through 'next'.
|
53
54
|
struct grpc_tcp_listener* sibling;
|
54
55
|
int is_sibling;
|
56
|
+
// If an accept4() call fails, a timer is started to drain the accept queue in
|
57
|
+
// case no further connection attempts reach the gRPC server.
|
58
|
+
grpc_closure retry_closure;
|
59
|
+
grpc_timer retry_timer;
|
60
|
+
gpr_atm retry_timer_armed;
|
55
61
|
} grpc_tcp_listener;
|
56
62
|
|
57
63
|
// the overall server
|
@@ -139,4 +145,10 @@ grpc_error_handle grpc_tcp_server_prepare_socket(
|
|
139
145
|
// Ruturn true if the platform supports ifaddrs
|
140
146
|
bool grpc_tcp_server_have_ifaddrs(void);
|
141
147
|
|
148
|
+
// Initialize (but don't start) the timer and callback to retry accept4() on a
|
149
|
+
// listening socket after file descriptors have been exhausted. This must be
|
150
|
+
// called when creating a new listener.
|
151
|
+
void grpc_tcp_server_listener_initialize_retry_timer(
|
152
|
+
grpc_tcp_listener* listener);
|
153
|
+
|
142
154
|
#endif // GRPC_SRC_CORE_LIB_IOMGR_TCP_SERVER_UTILS_POSIX_H
|
@@ -18,6 +18,8 @@
|
|
18
18
|
|
19
19
|
#include <grpc/support/port_platform.h>
|
20
20
|
|
21
|
+
#include <grpc/support/atm.h>
|
22
|
+
|
21
23
|
#include "src/core/lib/iomgr/port.h"
|
22
24
|
|
23
25
|
#ifdef GRPC_POSIX_SOCKET_TCP_SERVER_UTILS_COMMON
|
@@ -81,6 +83,24 @@ static int get_max_accept_queue_size(void) {
|
|
81
83
|
return s_max_accept_queue_size;
|
82
84
|
}
|
83
85
|
|
86
|
+
static void listener_retry_timer_cb(void* arg, grpc_error_handle err) {
|
87
|
+
// Do nothing if cancelled.
|
88
|
+
if (!err.ok()) return;
|
89
|
+
grpc_tcp_listener* listener = static_cast<grpc_tcp_listener*>(arg);
|
90
|
+
gpr_atm_no_barrier_store(&listener->retry_timer_armed, false);
|
91
|
+
if (!grpc_fd_is_shutdown(listener->emfd)) {
|
92
|
+
grpc_fd_set_readable(listener->emfd);
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
void grpc_tcp_server_listener_initialize_retry_timer(
|
97
|
+
grpc_tcp_listener* listener) {
|
98
|
+
gpr_atm_no_barrier_store(&listener->retry_timer_armed, false);
|
99
|
+
grpc_timer_init_unset(&listener->retry_timer);
|
100
|
+
GRPC_CLOSURE_INIT(&listener->retry_closure, listener_retry_timer_cb, listener,
|
101
|
+
grpc_schedule_on_exec_ctx);
|
102
|
+
}
|
103
|
+
|
84
104
|
static grpc_error_handle add_socket_to_server(grpc_tcp_server* s, int fd,
|
85
105
|
const grpc_resolved_address* addr,
|
86
106
|
unsigned port_index,
|
@@ -112,6 +132,7 @@ static grpc_error_handle add_socket_to_server(grpc_tcp_server* s, int fd,
|
|
112
132
|
sp->server = s;
|
113
133
|
sp->fd = fd;
|
114
134
|
sp->emfd = grpc_fd_create(fd, name.c_str(), true);
|
135
|
+
grpc_tcp_server_listener_initialize_retry_timer(sp);
|
115
136
|
|
116
137
|
// Check and set fd as prellocated
|
117
138
|
if (grpc_tcp_server_pre_allocated_fd(s) == fd) {
|
@@ -21,8 +21,6 @@
|
|
21
21
|
#include "src/core/lib/surface/validate_metadata.h"
|
22
22
|
|
23
23
|
#include "absl/status/status.h"
|
24
|
-
#include "absl/strings/escaping.h"
|
25
|
-
#include "absl/strings/str_cat.h"
|
26
24
|
#include "absl/strings/string_view.h"
|
27
25
|
|
28
26
|
#include <grpc/grpc.h>
|
@@ -46,32 +44,49 @@ class LegalHeaderKeyBits : public BitSet<256> {
|
|
46
44
|
};
|
47
45
|
constexpr LegalHeaderKeyBits g_legal_header_key_bits;
|
48
46
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
absl::BytesToHexString(x), ")"));
|
53
|
-
}
|
54
|
-
|
55
|
-
absl::Status ConformsTo(absl::string_view x, const BitSet<256>& legal_bits,
|
56
|
-
const char* err_desc) {
|
47
|
+
ValidateMetadataResult ConformsTo(absl::string_view x,
|
48
|
+
const BitSet<256>& legal_bits,
|
49
|
+
ValidateMetadataResult error) {
|
57
50
|
for (uint8_t c : x) {
|
58
51
|
if (!legal_bits.is_set(c)) {
|
59
|
-
return
|
52
|
+
return error;
|
60
53
|
}
|
61
54
|
}
|
62
|
-
return
|
55
|
+
return ValidateMetadataResult::kOk;
|
56
|
+
}
|
57
|
+
|
58
|
+
absl::Status UpgradeToStatus(ValidateMetadataResult result) {
|
59
|
+
if (result == ValidateMetadataResult::kOk) return absl::OkStatus();
|
60
|
+
return absl::InternalError(ValidateMetadataResultToString(result));
|
63
61
|
}
|
62
|
+
|
64
63
|
} // namespace
|
65
64
|
|
66
|
-
|
65
|
+
ValidateMetadataResult ValidateHeaderKeyIsLegal(absl::string_view key) {
|
67
66
|
if (key.empty()) {
|
68
|
-
return
|
67
|
+
return ValidateMetadataResult::kCannotBeZeroLength;
|
69
68
|
}
|
70
69
|
if (key.size() > UINT32_MAX) {
|
71
|
-
return
|
72
|
-
|
70
|
+
return ValidateMetadataResult::kTooLong;
|
71
|
+
}
|
72
|
+
return ConformsTo(key, g_legal_header_key_bits,
|
73
|
+
ValidateMetadataResult::kIllegalHeaderKey);
|
74
|
+
}
|
75
|
+
|
76
|
+
const char* ValidateMetadataResultToString(ValidateMetadataResult result) {
|
77
|
+
switch (result) {
|
78
|
+
case ValidateMetadataResult::kOk:
|
79
|
+
return "Ok";
|
80
|
+
case ValidateMetadataResult::kCannotBeZeroLength:
|
81
|
+
return "Metadata keys cannot be zero length";
|
82
|
+
case ValidateMetadataResult::kTooLong:
|
83
|
+
return "Metadata keys cannot be larger than UINT32_MAX";
|
84
|
+
case ValidateMetadataResult::kIllegalHeaderKey:
|
85
|
+
return "Illegal header key";
|
86
|
+
case ValidateMetadataResult::kIllegalHeaderValue:
|
87
|
+
return "Illegal header value";
|
73
88
|
}
|
74
|
-
return
|
89
|
+
GPR_UNREACHABLE_CODE(return "Unknown");
|
75
90
|
}
|
76
91
|
|
77
92
|
} // namespace grpc_core
|
@@ -82,8 +97,8 @@ static int error2int(grpc_error_handle error) {
|
|
82
97
|
}
|
83
98
|
|
84
99
|
grpc_error_handle grpc_validate_header_key_is_legal(const grpc_slice& slice) {
|
85
|
-
return grpc_core::ValidateHeaderKeyIsLegal(
|
86
|
-
grpc_core::StringViewFromSlice(slice));
|
100
|
+
return grpc_core::UpgradeToStatus(grpc_core::ValidateHeaderKeyIsLegal(
|
101
|
+
grpc_core::StringViewFromSlice(slice)));
|
87
102
|
}
|
88
103
|
|
89
104
|
int grpc_header_key_is_legal(grpc_slice slice) {
|
@@ -104,9 +119,9 @@ constexpr LegalHeaderNonBinValueBits g_legal_header_non_bin_value_bits;
|
|
104
119
|
|
105
120
|
grpc_error_handle grpc_validate_header_nonbin_value_is_legal(
|
106
121
|
const grpc_slice& slice) {
|
107
|
-
return grpc_core::
|
108
|
-
|
109
|
-
|
122
|
+
return grpc_core::UpgradeToStatus(grpc_core::ConformsTo(
|
123
|
+
grpc_core::StringViewFromSlice(slice), g_legal_header_non_bin_value_bits,
|
124
|
+
grpc_core::ValidateMetadataResult::kIllegalHeaderValue));
|
110
125
|
}
|
111
126
|
|
112
127
|
int grpc_header_nonbin_value_is_legal(grpc_slice slice) {
|
@@ -25,7 +25,6 @@
|
|
25
25
|
|
26
26
|
#include <cstring>
|
27
27
|
|
28
|
-
#include "absl/status/status.h"
|
29
28
|
#include "absl/strings/string_view.h"
|
30
29
|
|
31
30
|
#include <grpc/slice.h>
|
@@ -35,9 +34,20 @@
|
|
35
34
|
|
36
35
|
namespace grpc_core {
|
37
36
|
|
38
|
-
|
37
|
+
enum class ValidateMetadataResult : uint8_t {
|
38
|
+
kOk,
|
39
|
+
kCannotBeZeroLength,
|
40
|
+
kTooLong,
|
41
|
+
kIllegalHeaderKey,
|
42
|
+
kIllegalHeaderValue
|
43
|
+
};
|
39
44
|
|
40
|
-
|
45
|
+
const char* ValidateMetadataResultToString(ValidateMetadataResult result);
|
46
|
+
|
47
|
+
// Returns nullopt if the key is legal, otherwise returns an error message.
|
48
|
+
ValidateMetadataResult ValidateHeaderKeyIsLegal(absl::string_view key);
|
49
|
+
|
50
|
+
} // namespace grpc_core
|
41
51
|
|
42
52
|
grpc_error_handle grpc_validate_header_key_is_legal(const grpc_slice& slice);
|
43
53
|
grpc_error_handle grpc_validate_header_nonbin_value_is_legal(
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grpc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.55.
|
4
|
+
version: 1.55.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- gRPC Authors
|
8
8
|
autorequire:
|
9
9
|
bindir: src/ruby/bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-protobuf
|
@@ -462,6 +462,8 @@ files:
|
|
462
462
|
- src/core/ext/transport/chttp2/transport/hpack_encoder.h
|
463
463
|
- src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc
|
464
464
|
- src/core/ext/transport/chttp2/transport/hpack_encoder_table.h
|
465
|
+
- src/core/ext/transport/chttp2/transport/hpack_parse_result.cc
|
466
|
+
- src/core/ext/transport/chttp2/transport/hpack_parse_result.h
|
465
467
|
- src/core/ext/transport/chttp2/transport/hpack_parser.cc
|
466
468
|
- src/core/ext/transport/chttp2/transport/hpack_parser.h
|
467
469
|
- src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
|
@@ -3208,7 +3210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
3208
3210
|
- !ruby/object:Gem::Version
|
3209
3211
|
version: '0'
|
3210
3212
|
requirements: []
|
3211
|
-
rubygems_version: 3.4.
|
3213
|
+
rubygems_version: 3.4.17
|
3212
3214
|
signing_key:
|
3213
3215
|
specification_version: 4
|
3214
3216
|
summary: GRPC system in Ruby
|