hiredis-client 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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