grpc 1.53.1 → 1.53.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a379c4ca9a7aaaba1fc0daf741ff674124622bf473dc48ecc8c786ba7a9246a5
4
- data.tar.gz: 87ad7e100be1406e6b5d928d9f6af684dd0f2d5bb9fc7c9b5a15ab0fed668cc8
3
+ metadata.gz: 0c237088f6035b2dc6f188374ab0531f3f3b8307f61fdc5b8a57518bc02b222c
4
+ data.tar.gz: fb1aec781fd0bf129d3740eeed7fa432b0412f29ba4ec2da79b197bb903cb1bd
5
5
  SHA512:
6
- metadata.gz: 8022d820669d96ad0669842e80a0e8cc316fdd77f0c3843e1ab8bb899ed9ea829baecf08e31c81d0bb64c55ba6afe98c8ae693d46bdeeb83f7b7f6dbe25628dc
7
- data.tar.gz: eda257dbc42d4e994f67f7efacdf8c63078808b22e1adc92ec05a5ebdd1490fc1c49b87b6e88e32954dff09dacf53deb1c5517acbc00ddd8356de2200a0ad247
6
+ metadata.gz: b62ef23a0f40e77c274ceeb11b929e6fa61cf9b7ac381524ee5be37b5c64e45b8ddb4a7188442fc0387c7296fd67b77b775af93aea877f5ccb78ed9aa0a16573
7
+ data.tar.gz: 45fc670b35416ca8a2a1f133e512576a4cdd4d72ddc97506aa2dcc7aa650a90865a6acfba41bb3cded70a126702fa5736a0ffb8dea7e1ccb83df5a6a7633f0b5
data/Makefile CHANGED
@@ -411,8 +411,8 @@ Q = @
411
411
  endif
412
412
 
413
413
  CORE_VERSION = 30.1.0
414
- CPP_VERSION = 1.53.1
415
- CSHARP_VERSION = 2.53.1
414
+ CPP_VERSION = 1.53.2
415
+ CSHARP_VERSION = 2.53.2
416
416
 
417
417
  CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
418
418
  CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -196,6 +196,7 @@ class PosixEventEngine final : public PosixEventEngineWithFdSupport,
196
196
  const DNSResolver::ResolverOptions& options) override;
197
197
  void Run(Closure* closure) override;
198
198
  void Run(absl::AnyInvocable<void()> closure) override;
199
+ // Caution!! The timer implementation cannot create any fds. See #20418.
199
200
  TaskHandle RunAfter(Duration when, Closure* closure) override;
200
201
  TaskHandle RunAfter(Duration when,
201
202
  absl::AnyInvocable<void()> closure) override;
@@ -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 {
@@ -133,6 +136,32 @@ void PosixEngineListenerImpl::AsyncConnectionAcceptor::NotifyOnAccept(
133
136
  switch (errno) {
134
137
  case EINTR:
135
138
  continue;
139
+ case EMFILE:
140
+ // When the process runs out of fds, accept4() returns EMFILE. When
141
+ // this happens, the connection is left in the accept queue until
142
+ // either a read event triggers the on_read callback, or time has
143
+ // passed and the accept should be re-tried regardless. This callback
144
+ // is not cancelled, so a spurious wakeup may occur even when there's
145
+ // nothing to accept. This is not a performant code path, but if an fd
146
+ // limit has been reached, the system is likely in an unhappy state
147
+ // regardless.
148
+ GRPC_LOG_EVERY_N_SEC(1, "%s",
149
+ "File descriptor limit reached. Retrying.");
150
+ handle_->NotifyOnRead(notify_on_accept_);
151
+ // Do not schedule another timer if one is already armed.
152
+ if (retry_timer_armed_.exchange(true)) return;
153
+ // Hold a ref while the retry timer is waiting, to prevent listener
154
+ // destruction and the races that would ensue.
155
+ Ref();
156
+ std::ignore =
157
+ engine_->RunAfter(grpc_core::Duration::Seconds(1), [this]() {
158
+ retry_timer_armed_.store(false);
159
+ if (!handle_->IsHandleShutdown()) {
160
+ handle_->SetReadable();
161
+ }
162
+ Unref();
163
+ });
164
+ return;
136
165
  case EAGAIN:
137
166
  case ECONNABORTED:
138
167
  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>
@@ -74,6 +79,8 @@
74
79
  #include "src/core/lib/transport/error_utils.h"
75
80
 
76
81
  static std::atomic<int64_t> num_dropped_connections{0};
82
+ static constexpr grpc_core::Duration kRetryAcceptWaitTime{
83
+ grpc_core::Duration::Seconds(1)};
77
84
 
78
85
  using ::grpc_event_engine::experimental::EndpointConfig;
79
86
  using ::grpc_event_engine::experimental::EventEngine;
@@ -350,22 +357,38 @@ static void on_read(void* arg, grpc_error_handle err) {
350
357
  if (fd < 0) {
351
358
  if (errno == EINTR) {
352
359
  continue;
353
- } else if (errno == EAGAIN || errno == ECONNABORTED ||
354
- errno == EWOULDBLOCK) {
360
+ }
361
+ // When the process runs out of fds, accept4() returns EMFILE. When this
362
+ // happens, the connection is left in the accept queue until either a
363
+ // read event triggers the on_read callback, or time has passed and the
364
+ // accept should be re-tried regardless. This callback is not cancelled,
365
+ // so a spurious wakeup may occur even when there's nothing to accept.
366
+ // This is not a performant code path, but if an fd limit has been
367
+ // reached, the system is likely in an unhappy state regardless.
368
+ if (errno == EMFILE) {
369
+ GRPC_LOG_EVERY_N_SEC(1, "%s",
370
+ "File descriptor limit reached. Retrying.");
371
+ grpc_fd_notify_on_read(sp->emfd, &sp->read_closure);
372
+ if (gpr_atm_full_xchg(&sp->retry_timer_armed, true)) return;
373
+ grpc_timer_init(&sp->retry_timer,
374
+ grpc_core::Timestamp::Now() + kRetryAcceptWaitTime,
375
+ &sp->retry_closure);
376
+ return;
377
+ }
378
+ if (errno == EAGAIN || errno == ECONNABORTED || errno == EWOULDBLOCK) {
355
379
  grpc_fd_notify_on_read(sp->emfd, &sp->read_closure);
356
380
  return;
381
+ }
382
+ gpr_mu_lock(&sp->server->mu);
383
+ if (!sp->server->shutdown_listeners) {
384
+ gpr_log(GPR_ERROR, "Failed accept4: %s",
385
+ grpc_core::StrError(errno).c_str());
357
386
  } else {
358
- gpr_mu_lock(&sp->server->mu);
359
- if (!sp->server->shutdown_listeners) {
360
- gpr_log(GPR_ERROR, "Failed accept4: %s",
361
- grpc_core::StrError(errno).c_str());
362
- } else {
363
- // if we have shutdown listeners, accept4 could fail, and we
364
- // needn't notify users
365
- }
366
- gpr_mu_unlock(&sp->server->mu);
367
- goto error;
387
+ // if we have shutdown listeners, accept4 could fail, and we
388
+ // needn't notify users
368
389
  }
390
+ gpr_mu_unlock(&sp->server->mu);
391
+ goto error;
369
392
  }
370
393
 
371
394
  if (sp->server->memory_quota->IsMemoryPressureHigh()) {
@@ -558,6 +581,7 @@ static grpc_error_handle clone_port(grpc_tcp_listener* listener,
558
581
  sp->port_index = listener->port_index;
559
582
  sp->fd_index = listener->fd_index + count - i;
560
583
  GPR_ASSERT(sp->emfd);
584
+ grpc_tcp_server_listener_initialize_retry_timer(sp);
561
585
  while (listener->server->tail->next != nullptr) {
562
586
  listener->server->tail = listener->server->tail->next;
563
587
  }
@@ -791,6 +815,7 @@ static void tcp_server_shutdown_listeners(grpc_tcp_server* s) {
791
815
  if (s->active_ports) {
792
816
  grpc_tcp_listener* sp;
793
817
  for (sp = s->head; sp; sp = sp->next) {
818
+ grpc_timer_cancel(&sp->retry_timer);
794
819
  grpc_fd_shutdown(sp->emfd, GRPC_ERROR_CREATE("Server shutdown"));
795
820
  }
796
821
  }
@@ -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) {
@@ -14,5 +14,5 @@
14
14
 
15
15
  # GRPC contains the General RPC module.
16
16
  module GRPC
17
- VERSION = '1.53.1'
17
+ VERSION = '1.53.2'
18
18
  end
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.53.1
4
+ version: 1.53.2
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-05-11 00:00:00.000000000 Z
11
+ date: 2023-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: google-protobuf
@@ -3060,7 +3060,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
3060
3060
  - !ruby/object:Gem::Version
3061
3061
  version: '0'
3062
3062
  requirements: []
3063
- rubygems_version: 3.4.13
3063
+ rubygems_version: 3.4.17
3064
3064
  signing_key:
3065
3065
  specification_version: 4
3066
3066
  summary: GRPC system in Ruby