hiredis-client 0.9.0 → 0.11.0

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: 834e7347f7934e084b79647b8a179f2297e9e3ef29fce477a0d4a7c76ed99989
4
- data.tar.gz: 121469ded1e076737990f7c6ce1ec86666cf4194dca2707fd1fa5645b63c3d6d
3
+ metadata.gz: 4c30e3ee9498ead669c8f956cdd01a5f5c461af38a8eedaca5726622663d5284
4
+ data.tar.gz: '086288891e30a5b1966b60279af5eb7b3573a5cbb35ce64b974ca289a9eedbf1'
5
5
  SHA512:
6
- metadata.gz: 8f67fbd4582aaadbe6d7a2da0ce68bf45a9a712914e270de8e97511af579905033bfa5aa83c6055a38771078be87cdbb36e0883f5be471cfb3feb92cc5363007
7
- data.tar.gz: 114644f547ddf1c707f76b04d53a8876d06f075aa66056d7185edcd86143643307dd06265e5f7a1446af0f207ac7c547f07e5ff9799c8b69b1816e4735c6f266
6
+ metadata.gz: be4dd95865da29525ee3a6ce4b1cc8c7c3813e6589a3dc97a6270dc8bdbe99803cfe46c581ab4f255d2b9e8470e3dc9557d30061870c266197974703da5447f7
7
+ data.tar.gz: 17015559919a8008b8ad66cf743134f16cb91c19be7c97685faa0bb8a02b49dabdb66986eadc00269af61ace4e9ce62a0b336d0619d64fb56beccaa1364b75ff
@@ -311,14 +311,28 @@ static VALUE hiredis_alloc(VALUE klass) {
311
311
  return TypedData_Make_Struct(klass, hiredis_connection_t, &hiredis_connection_data_type, connection);
312
312
  }
313
313
 
314
+ void redis_set_io_error(redisContext *context, int err) {
315
+ if (err) {
316
+ errno = err;
317
+ }
318
+ context->err = REDIS_ERR_IO;
319
+ (void)!strerror_r(errno, context->errstr, sizeof(context->errstr));
320
+ }
321
+
314
322
  static inline void redis_raise_error_and_disconnect(redisContext *context, VALUE timeout_error) {
315
323
  if (!context) return;
316
324
 
317
325
  int err = context->err;
318
326
  char errstr[128];
319
- MEMCPY(context->errstr, errstr, char, 128);
327
+ if (context->err) {
328
+ strncpy(errstr, context->errstr, 128);
329
+ }
320
330
  redisFree(context);
321
331
 
332
+ if (!err) {
333
+ rb_raise(timeout_error, "Unknown Error");
334
+ }
335
+
322
336
  // OpenSSL bug: The SSL_ERROR_SYSCALL with errno value of 0 indicates unexpected EOF from the peer.
323
337
  if (errno == EAGAIN || (err == REDIS_ERR_IO && errno == 0)) {
324
338
  errno = 0;
@@ -431,26 +445,28 @@ static VALUE hiredis_connect_finish(hiredis_connection_t *connection, redisConte
431
445
 
432
446
  int writable = 0;
433
447
  int optval = 0;
448
+ errno = 0;
434
449
  socklen_t optlen = sizeof(optval);
435
450
 
436
451
  /* Wait for socket to become writable */
437
452
  if (hiredis_wait_writable(context->fd, &connection->connect_timeout, &writable) < 0) {
453
+ redis_set_io_error(context, ETIMEDOUT);
438
454
  redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
439
455
  }
440
456
 
441
457
  if (!writable) {
442
- errno = ETIMEDOUT;
458
+ redis_set_io_error(context, ETIMEDOUT);
443
459
  redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
444
460
  }
445
461
 
446
462
  /* Check for socket error */
447
463
  if (getsockopt(context->fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0) {
448
- context->err = REDIS_ERR_IO;
464
+ redis_set_io_error(context, 0);
449
465
  redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
450
466
  }
451
467
 
452
468
  if (optval) {
453
- errno = optval;
469
+ redis_set_io_error(context, optval);
454
470
  redis_raise_error_and_disconnect(context, rb_eRedisClientCannotConnectError);
455
471
  }
456
472
 
@@ -602,14 +618,17 @@ static VALUE hiredis_flush(VALUE self) {
602
618
  return Qtrue;
603
619
  }
604
620
 
621
+
622
+ #define HIREDIS_FATAL_CONNECTION_ERROR -1
623
+ #define HIREDIS_CLIENT_TIMEOUT -2
624
+
605
625
  static int hiredis_read_internal(hiredis_connection_t *connection, VALUE *reply) {
606
626
  void *redis_reply = NULL;
607
627
  int wdone = 0;
608
628
 
609
629
  /* Try to read pending replies */
610
630
  if (redisGetReplyFromReader(connection->context, &redis_reply) == REDIS_ERR) {
611
- /* Protocol error */
612
- return -1;
631
+ return HIREDIS_FATAL_CONNECTION_ERROR; // Protocol error
613
632
  }
614
633
 
615
634
  if (redis_reply == NULL) {
@@ -618,20 +637,19 @@ static int hiredis_read_internal(hiredis_connection_t *connection, VALUE *reply)
618
637
  errno = 0;
619
638
 
620
639
  if (hiredis_buffer_write_nogvl(connection->context, &wdone) == REDIS_ERR) {
621
- /* Socket error */
622
- return -1;
640
+ return HIREDIS_FATAL_CONNECTION_ERROR; // Socket error
623
641
  }
624
642
 
625
643
  if (errno == EAGAIN) {
626
644
  int writable = 0;
627
645
 
628
646
  if (hiredis_wait_writable(connection->context->fd, &connection->write_timeout, &writable) < 0) {
629
- return -2;
647
+ return HIREDIS_CLIENT_TIMEOUT;
630
648
  }
631
649
 
632
650
  if (!writable) {
633
651
  errno = EAGAIN;
634
- return -2;
652
+ return HIREDIS_CLIENT_TIMEOUT;
635
653
  }
636
654
  }
637
655
  }
@@ -641,20 +659,19 @@ static int hiredis_read_internal(hiredis_connection_t *connection, VALUE *reply)
641
659
  errno = 0;
642
660
 
643
661
  if (hiredis_buffer_read_nogvl(connection->context) == REDIS_ERR) {
644
- /* Socket error */
645
- return -1;
662
+ return HIREDIS_FATAL_CONNECTION_ERROR; // Socket error
646
663
  }
647
664
 
648
665
  if (errno == EAGAIN) {
649
666
  int readable = 0;
650
667
 
651
668
  if (hiredis_wait_readable(connection->context->fd, &connection->read_timeout, &readable) < 0) {
652
- return -2;
669
+ return HIREDIS_CLIENT_TIMEOUT;
653
670
  }
654
671
 
655
672
  if (!readable) {
656
673
  errno = EAGAIN;
657
- return -2;
674
+ return HIREDIS_CLIENT_TIMEOUT;
658
675
  }
659
676
 
660
677
  /* Retry */
@@ -662,8 +679,7 @@ static int hiredis_read_internal(hiredis_connection_t *connection, VALUE *reply)
662
679
  }
663
680
 
664
681
  if (redisGetReplyFromReader(connection->context, &redis_reply) == REDIS_ERR) {
665
- /* Protocol error */
666
- return -1;
682
+ return HIREDIS_FATAL_CONNECTION_ERROR; // Protocol error
667
683
  }
668
684
  }
669
685
  }
@@ -681,9 +697,19 @@ static VALUE hiredis_read(VALUE self) {
681
697
  ENSURE_CONNECTED(connection);
682
698
 
683
699
  VALUE reply = Qnil;
684
- if (hiredis_read_internal(connection, &reply)) {
685
- hiredis_raise_error_and_disconnect(connection, rb_eRedisClientReadTimeoutError);
700
+ switch (hiredis_read_internal(connection, &reply)) {
701
+ case HIREDIS_FATAL_CONNECTION_ERROR:
702
+ // The error is unrecoverable, we eagerly close the connection to ensure
703
+ // it won't be re-used.
704
+ hiredis_raise_error_and_disconnect(connection, rb_eRedisClientReadTimeoutError);
705
+ break;
706
+ case HIREDIS_CLIENT_TIMEOUT:
707
+ // The timeout might have been expected (e.g. `PubSub#next_event`).
708
+ // we let the caller decide if the connection should be closed.
709
+ rb_raise(rb_eRedisClientReadTimeoutError, "Unknown Error");
710
+ break;
686
711
  }
712
+
687
713
  if (reply == Redis_Qfalse) {
688
714
  // See reply_create_bool
689
715
  reply = Qfalse;
@@ -935,8 +935,9 @@ int redisBufferRead(redisContext *c) {
935
935
  int nread;
936
936
 
937
937
  /* Return early when the context has seen an error. */
938
- if (c->err)
938
+ if (c->err) {
939
939
  return REDIS_ERR;
940
+ }
940
941
 
941
942
  nread = c->funcs->read(c, buf, sizeof(buf));
942
943
  if (nread > 0) {
@@ -41,7 +41,12 @@ class RedisClient
41
41
  raise CannotConnectError, error.message, error.backtrace
42
42
  end
43
43
  else
44
- connect_tcp(config.host, config.port)
44
+ begin
45
+ connect_tcp(config.host, config.port)
46
+ rescue SystemCallError => error
47
+ error_code = error.class.name.split("::").last
48
+ raise CannotConnectError, "Failed to connect to #{config.host}:#{config.port} (#{error_code})"
49
+ end
45
50
  end
46
51
 
47
52
  if config.ssl
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiredis-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-22 00:00:00.000000000 Z
11
+ date: 2022-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.9.0
19
+ version: 0.11.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.9.0
26
+ version: 0.11.0
27
27
  description:
28
28
  email:
29
29
  - jean.boussier@gmail.com