iodine 0.7.20 → 0.7.21

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69bfcfdbbca3218b3e1865afa22a9ccfcbeb8cbbe5eadacbcac978b3bb11d1ec
4
- data.tar.gz: 474d23c9adfd030ef247fb695630ea7a81337170f173aa25ac898689605dcaef
3
+ metadata.gz: b0f9360224da57145ba3ed9e81d5e5472cf9bb9732c9d36fab6e22c32428013a
4
+ data.tar.gz: e04fc9d016bbb53cf80d810765a5b934d0d996d447faadd6451c27612cd17da6
5
5
  SHA512:
6
- metadata.gz: b30cb2e9178c39a10458af0368733d2b35dda7f2d5b3a95870ee3147f782a29fd4270358606c7be8459a8924f383bfcb382feb45f58f59bab181fdc158728ca0
7
- data.tar.gz: 1ced424fdbc203a0e8efc9739b6a9cd99b3f4bf616f482f677ff9a6c87a336a9c453563d8338f3fc908ed50150699fd1d9bb5a11de4eb69da93869403685791b
6
+ metadata.gz: 970307f1349dd8ca00a6caa6bfb59c6485f05fdb0b1654dd2788f3b477f628aa9b1c24a9df0873409930dd071dc446e999164731892fe7d70a64983f49a72d99
7
+ data.tar.gz: aa2417372b97f415ee83edd7aa0ecd557cef4144eba546cd931bc36078574cc03b574f16a395a779957015084c1737b996d13337516ac474efa78d4140075035
@@ -6,9 +6,17 @@ Please notice that this change log contains changes for upcoming releases as wel
6
6
 
7
7
  ## Changes:
8
8
 
9
+ #### Change log v.0.7.21
10
+
11
+ **Fix**: (`iodine`, `redis`) Redis response was attempting to create Ruby objects outside the GIL. This is now fixed by entering the GIL earlier (before objects are created). Credit to @moxgeek (Marouane Elmidaoui) for exposing this issue (plezi#31).
12
+
13
+ **Fix**: (`redis`) fixed Redis reconnection. Address and port data was mistakingly written at the wrong address, causing it to be overwritten by incoming (non-pub/sub) data.
14
+
15
+ **Fix**: (`redis`) fixed a race condition in the Redis reconnection logic which might have caused more then a single pub/sub connection to be established and the first pending command to be sent again.
16
+
9
17
  #### Change log v.0.7.20
10
18
 
11
- **Security**: (`fio`) lower Slowloris detection limits (backlog limit is now 1,024 responses / messages per client).
19
+ **Security**: (`fio`) lower and smarter Slowloris detection limits (backlog limit is now 1,024 responses / messages per client).
12
20
 
13
21
  **Security**: (`http`) HTTP/1.1 slow client throttling - new requests will not be consumed until pending responses were sent. Since HTTP/1.1 is a response-request protocol, this protocol specific approach should protect the HTTP application against slow clients.
14
22
 
@@ -32,7 +32,7 @@ module ShootoutApp
32
32
  end
33
33
  def self.on_message client, data
34
34
  if data[0] == 'b' # binary
35
- client.publish :shootout_b, data
35
+ client.publish :shootout_b, data
36
36
  data[0] = 'r'
37
37
  client.write data
38
38
  return
@@ -2901,42 +2901,32 @@ void fio_force_close(intptr_t uuid) {
2901
2901
  * error or when the connection is closed.
2902
2902
  */
2903
2903
  ssize_t fio_flush(intptr_t uuid) {
2904
- if (!uuid_is_valid(uuid)) {
2905
- errno = EBADF;
2906
- return -1;
2907
- }
2908
- ssize_t flushed;
2904
+ if (!uuid_is_valid(uuid))
2905
+ goto invalid;
2906
+ errno = 0;
2907
+ ssize_t flushed = 0;
2909
2908
  int tmp;
2910
2909
  /* start critical section */
2911
2910
  if (fio_trylock(&uuid_data(uuid).sock_lock))
2912
2911
  goto would_block;
2913
2912
 
2914
- if (uuid_data(uuid).packet) {
2915
- tmp = uuid_data(uuid).packet->write_func(fio_uuid2fd(uuid),
2916
- uuid_data(uuid).packet);
2917
- const size_t old_count = uuid_data(uuid).packet_count;
2918
- if (tmp == 0) {
2919
- errno = ECONNRESET;
2920
- fio_unlock(&uuid_data(uuid).sock_lock);
2921
- uuid_data(uuid).close = 1;
2922
- goto closed;
2923
- } else if (tmp < 0) {
2924
- goto test_errno;
2925
- }
2913
+ if (!uuid_data(uuid).packet)
2914
+ goto flush_rw_hook;
2926
2915
 
2927
- if (old_count >= 1024 && uuid_data(uuid).packet_count == old_count) {
2928
- /* Slowloris attack assumed */
2929
- goto attacked;
2930
- }
2916
+ const size_t old_count = uuid_data(uuid).packet_count;
2917
+ const size_t old_sent = uuid_data(uuid).sent;
2931
2918
 
2932
- } else {
2933
- flushed = uuid_data(uuid).rw_hooks->flush(uuid, uuid_data(uuid).rw_udata);
2934
- if (flushed < 0) {
2935
- goto test_errno;
2936
- }
2937
- if (flushed) {
2938
- goto flushed;
2939
- }
2919
+ tmp = uuid_data(uuid).packet->write_func(fio_uuid2fd(uuid),
2920
+ uuid_data(uuid).packet);
2921
+ if (tmp <= 0) {
2922
+ goto test_errno;
2923
+ }
2924
+
2925
+ if (old_count >= 1024 && uuid_data(uuid).packet_count == old_count &&
2926
+ uuid_data(uuid).sent >= old_sent &&
2927
+ (uuid_data(uuid).sent - old_sent) < 32768) {
2928
+ /* Slowloris attack assumed */
2929
+ goto attacked;
2940
2930
  }
2941
2931
 
2942
2932
  /* end critical section */
@@ -2952,22 +2942,48 @@ ssize_t fio_flush(intptr_t uuid) {
2952
2942
  would_block:
2953
2943
  errno = EWOULDBLOCK;
2954
2944
  return -1;
2945
+
2955
2946
  closed:
2956
2947
  fio_force_close(uuid);
2957
2948
  return -1;
2949
+
2950
+ flush_rw_hook:
2951
+ flushed = uuid_data(uuid).rw_hooks->flush(uuid, uuid_data(uuid).rw_udata);
2952
+ fio_unlock(&uuid_data(uuid).sock_lock);
2953
+ if (!flushed)
2954
+ return 0;
2955
+ if (flushed < 0) {
2956
+ goto test_errno;
2957
+ }
2958
+ touchfd(fio_uuid2fd(uuid));
2959
+ return 1;
2960
+
2958
2961
  test_errno:
2959
2962
  fio_unlock(&uuid_data(uuid).sock_lock);
2960
- if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ENOTCONN ||
2961
- errno == EINPROGRESS || errno == ENOSPC || errno == EINTR) {
2963
+ switch (errno) {
2964
+ case EWOULDBLOCK: /* ovreflow */
2965
+ #if EWOULDBLOCK != EAGAIN
2966
+ case EAGAIN: /* ovreflow */
2967
+ #endif
2968
+ case ENOTCONN: /* ovreflow */
2969
+ case EINPROGRESS: /* ovreflow */
2970
+ case ENOSPC: /* ovreflow */
2971
+ case EINTR:
2962
2972
  return 1;
2973
+ case EPIPE: /* ovreflow */
2974
+ case EIO: /* ovreflow */
2975
+ case EINVAL: /* ovreflow */
2976
+ case EBADF:
2977
+ uuid_data(uuid).close = 1;
2978
+ fio_force_close(uuid);
2979
+ return -1;
2963
2980
  }
2964
2981
  return 0;
2965
2982
 
2983
+ invalid:
2984
+ /* bad UUID */
2985
+ errno = EBADF;
2966
2986
  return -1;
2967
- flushed:
2968
- touchfd(fio_uuid2fd(uuid));
2969
- fio_unlock(&uuid_data(uuid).sock_lock);
2970
- return 1;
2971
2987
 
2972
2988
  attacked:
2973
2989
  /* don't close, just detach from facil.io and mark uuid as invalid */
@@ -6508,6 +6524,8 @@ static inline void fio_publish2process2(int32_t filter, fio_str_info_s ch_name,
6508
6524
  fio_pubsub_create_message(filter, ch_name, msg, is_json, 1));
6509
6525
  }
6510
6526
 
6527
+ /* Sublime Text marker */
6528
+ void fio_publish___(fio_publish_args_s args);
6511
6529
  /**
6512
6530
  * Publishes a message to the relevant subscribers (if any).
6513
6531
  *
@@ -8763,6 +8781,8 @@ FIO_FUNC inline void fio_llist_test(void) {
8763
8781
  FIO_ASSERT_ALLOC(n);
8764
8782
  n->i = i;
8765
8783
  fio_ls_embd_push(&emlist, &n->node);
8784
+ FIO_ASSERT(FIO_LS_EMBD_OBJ(struct fio_ls_test_s, node, emlist.next)->i == 0,
8785
+ "fio_ls_embd_push should push to the end.");
8766
8786
  }
8767
8787
  FIO_ASSERT(fio_ls_embd_any(&emlist),
8768
8788
  "List should be populated after fio_ls_embd_push");
@@ -8794,6 +8814,8 @@ FIO_FUNC inline void fio_llist_test(void) {
8794
8814
  FIO_ASSERT_ALLOC(n)
8795
8815
  n->i = i;
8796
8816
  fio_ls_embd_unshift(&emlist, &n->node);
8817
+ FIO_ASSERT(FIO_LS_EMBD_OBJ(struct fio_ls_test_s, node, emlist.next)->i == i,
8818
+ "fio_ls_embd_unshift should push to the start.");
8797
8819
  }
8798
8820
  FIO_ASSERT(fio_ls_embd_any(&emlist),
8799
8821
  "List should be populated after fio_ls_embd_unshift");
@@ -427,9 +427,16 @@ int __attribute__((weak)) FIO_LOG_LEVEL;
427
427
  int len___log = \
428
428
  snprintf(tmp___log, FIO_LOG_LENGTH_LIMIT - 2, __VA_ARGS__); \
429
429
  if (len___log <= 0 || len___log >= FIO_LOG_LENGTH_LIMIT - 2) { \
430
- fwrite("ERROR: log line output too long (can't write).", 46, 1, \
431
- stderr); \
432
- break; \
430
+ if (len___log >= (FIO_LOG_LENGTH_LIMIT >> 2) && \
431
+ (FIO_LOG_LENGTH_LIMIT >> 2) + 52 < FIO_LOG_LENGTH_LIMIT) { \
432
+ fwrite(tmp___log, (FIO_LOG_LENGTH_LIMIT >> 2), 1, stderr); \
433
+ memcpy(tmp___log + (FIO_LOG_LENGTH_LIMIT >> 2), \
434
+ "...\nERROR: log line output too long (can't write).\n", 52); \
435
+ len___log = (FIO_LOG_LENGTH_LIMIT >> 2) + 52; \
436
+ } else { \
437
+ fwrite("ERROR: log output error (can't write).\n", 39, 1, stderr); \
438
+ break; \
439
+ } \
433
440
  } \
434
441
  tmp___log[len___log++] = '\n'; \
435
442
  tmp___log[len___log] = '0'; \
@@ -676,11 +676,8 @@ Connection Callbacks
676
676
  ***************************************************************************** */
677
677
 
678
678
  static inline void http1_consume_data(intptr_t uuid, http1pr_s *p) {
679
- if (fio_pending(uuid) > 4) { /* throttle busy clients (slowloris) */
680
- fio_suspend(uuid);
681
- FIO_LOG_DEBUG("(HTTP/1,1) throttling client at %.*s",
682
- (int)fio_peer_addr(uuid).len, fio_peer_addr(uuid).data);
683
- return;
679
+ if (fio_pending(uuid) > 4) {
680
+ goto throttle;
684
681
  }
685
682
  ssize_t i = 0;
686
683
  size_t org_len = p->buf_len;
@@ -720,6 +717,13 @@ static inline void http1_consume_data(intptr_t uuid, http1pr_s *p) {
720
717
  if (!pipeline_limit) {
721
718
  fio_force_event(uuid, FIO_EVENT_ON_DATA);
722
719
  }
720
+ return;
721
+
722
+ throttle:
723
+ /* throttle busy clients (slowloris) */
724
+ fio_suspend(uuid);
725
+ FIO_LOG_DEBUG("(HTTP/1,1) throttling client at %.*s",
726
+ (int)fio_peer_addr(uuid).len, fio_peer_addr(uuid).data);
723
727
  }
724
728
 
725
729
  /** called when a data is available, but will not run concurrently */
@@ -110,7 +110,7 @@ static inline VALUE fiobj2rb_deep(FIOBJ obj, uint8_t str2sym) {
110
110
  while (fiobj_ary_pop(data.stack))
111
111
  ;
112
112
  fiobj_free(data.stack);
113
- IodineStore.remove(data.rb);
113
+ // IodineStore.remove(data.rb); // don't remove data
114
114
  return data.rb;
115
115
  }
116
116
 
@@ -185,6 +185,7 @@ static inline VALUE iodine_json_convert(VALUE str, fiobj2rb_settings_s s) {
185
185
  // }
186
186
  // VALUE ret = fiobj2rb_deep(json, s.str2sym);
187
187
  // fiobj_free(json);
188
+ // IodineStore.remove(ret);
188
189
  // return ret;
189
190
  // }
190
191
 
@@ -181,6 +181,7 @@ static void iodine_pubsub_data_mark(void *c_) {
181
181
  }
182
182
  /* a callback for the GC (marking active objects) */
183
183
  static void iodine_pubsub_data_free(void *c_) {
184
+ FIO_LOG_DEBUG("iodine destroying engine");
184
185
  iodine_pubsub_s *data = c_;
185
186
  fio_pubsub_detach(data->engine);
186
187
  IodineStore.remove(data->handler); /* redundant except during exit */
@@ -411,20 +412,32 @@ static VALUE iodine_pubsub_redis_new(int argc, VALUE *argv, VALUE self) {
411
412
  (void)argv;
412
413
  }
413
414
 
415
+ struct redis_callback_data {
416
+ FIOBJ response;
417
+ VALUE block;
418
+ };
419
+
420
+ /** A callback for Redis commands. */
421
+ static void *iodine_pubsub_redis_callback_in_gil(void *data_) {
422
+ struct redis_callback_data *d = data_;
423
+ VALUE rb = Qnil;
424
+ if (!FIOBJ_IS_NULL(d->response)) {
425
+ rb = fiobj2rb_deep(d->response, 0);
426
+ }
427
+ IodineCaller.call2(d->block, call_id, 1, &rb);
428
+ IodineStore.remove(rb);
429
+ return NULL;
430
+ }
431
+
414
432
  /** A callback for Redis commands. */
415
433
  static void iodine_pubsub_redis_callback(fio_pubsub_engine_s *e, FIOBJ response,
416
434
  void *udata) {
417
- VALUE block = (VALUE)udata;
418
- if (block == Qnil) {
435
+ struct redis_callback_data d = {.response = response, .block = (VALUE)udata};
436
+ if (d.block == Qnil) {
419
437
  return;
420
438
  }
421
- VALUE rb = Qnil;
422
- if (!FIOBJ_IS_NULL(response)) {
423
- rb = IodineStore.add(fiobj2rb_deep(response, 0));
424
- }
425
- IodineCaller.call2(block, call_id, 1, &rb);
426
- IodineStore.remove(rb);
427
- IodineStore.remove(block);
439
+ IodineCaller.enterGVL(iodine_pubsub_redis_callback_in_gil, &d);
440
+ IodineStore.remove(d.block);
428
441
  (void)e;
429
442
  }
430
443
 
@@ -44,8 +44,9 @@ typedef struct {
44
44
  size_t ref;
45
45
  fio_ls_embd_s queue;
46
46
  fio_lock_i lock;
47
+ fio_lock_i lock_connection;
47
48
  uint8_t ping_int;
48
- uint8_t pub_send;
49
+ volatile uint8_t pub_sent;
49
50
  volatile uint8_t flag;
50
51
  uint8_t buf[];
51
52
  } redis_engine_s;
@@ -84,6 +85,7 @@ static inline void redis_internal_reset(struct redis_engine_internal_s *i) {
84
85
  static inline void redis_free(redis_engine_s *r) {
85
86
  if (fio_atomic_sub(&r->ref, 1))
86
87
  return;
88
+ FIO_LOG_DEBUG("freeing redis engine for %s:%s", r->address, r->port);
87
89
  redis_internal_reset(&r->pub_data);
88
90
  redis_internal_reset(&r->sub_data);
89
91
  fiobj_free(r->last_ch);
@@ -310,30 +312,42 @@ static void redis_perform_callback(void *e, void *cmd_) {
310
312
  fio_free(cmd);
311
313
  }
312
314
 
315
+ /* send command within lock, to ensure flag integrity */
316
+ static void redis_send_next_command_unsafe(redis_engine_s *r) {
317
+ if (!r->pub_sent && fio_ls_embd_any(&r->queue)) {
318
+ r->pub_sent = 1;
319
+ redis_commands_s *cmd =
320
+ FIO_LS_EMBD_OBJ(redis_commands_s, node, r->queue.next);
321
+ fio_write2(r->pub_data.uuid, .data.buffer = cmd->cmd,
322
+ .length = cmd->cmd_len, .after.dealloc = FIO_DEALLOC_NOOP);
323
+ FIO_LOG_DEBUG("(redis %d) Sending (%zu bytes):\n%s\n", getpid(),
324
+ cmd->cmd_len, cmd->cmd);
325
+ }
326
+ }
327
+
313
328
  /* attach a command to the queue */
314
329
  static void redis_attach_cmd(redis_engine_s *r, redis_commands_s *cmd) {
315
330
  fio_lock(&r->lock);
316
331
  fio_ls_embd_push(&r->queue, &cmd->node);
317
- if (r->pub_send) {
318
- fio_write2(r->pub_data.uuid, .data.buffer = cmd->cmd,
319
- .length = cmd->cmd_len, .after.dealloc = FIO_DEALLOC_NOOP);
320
- FIO_LOG_DEBUG("(%d) Sending (%zu bytes):\n%s\n", getpid(), cmd->cmd_len,
321
- cmd->cmd);
322
- }
332
+ redis_send_next_command_unsafe(r);
323
333
  fio_unlock(&r->lock);
324
334
  }
325
335
 
326
336
  /** a local static callback, called when the RESP message is complete. */
327
337
  static void resp_on_pub_message(struct redis_engine_internal_s *i, FIOBJ msg) {
328
338
  redis_engine_s *r = pub2redis(i);
329
- #if DEBUG
330
- FIOBJ json = fiobj_obj2json(msg, 1);
331
- FIO_LOG_DEBUG("Redis reply:\n%s\n", fiobj_obj2cstr(json).data);
332
- fiobj_free(json);
333
- #endif
339
+ // #if DEBUG
340
+ if (FIO_LOG_LEVEL >= FIO_LOG_LEVEL_DEBUG) {
341
+ FIOBJ json = fiobj_obj2json(msg, 1);
342
+ FIO_LOG_DEBUG("Redis reply:\n%s\n", fiobj_obj2cstr(json).data);
343
+ fiobj_free(json);
344
+ }
345
+ // #endif
334
346
  /* publishing / command parser */
335
347
  fio_lock(&r->lock);
336
348
  fio_ls_embd_s *node = fio_ls_embd_shift(&r->queue);
349
+ r->pub_sent = 0;
350
+ redis_send_next_command_unsafe(r);
337
351
  fio_unlock(&r->lock);
338
352
  if (!node) {
339
353
  /* TODO: possible ping? from server?! not likely... */
@@ -358,8 +372,8 @@ static void resp_on_sub_message(struct redis_engine_internal_s *i, FIOBJ msg) {
358
372
  if (FIOBJ_TYPE(msg) != FIOBJ_T_STRING || fiobj_obj2cstr(msg).len != 4 ||
359
373
  fiobj_obj2cstr(msg).data[0] != 'P') {
360
374
  FIO_LOG_WARNING("(redis) unexpected data format in "
361
- "subscription stream:\n %s",
362
- fiobj_obj2cstr(msg).data);
375
+ "subscription stream (%zu bytes):\n %s\n",
376
+ fiobj_obj2cstr(msg).len, fiobj_obj2cstr(msg).data);
363
377
  }
364
378
  } else {
365
379
  // FIOBJ *ary = fiobj_ary2ptr(msg);
@@ -410,6 +424,7 @@ static void redis_on_data(intptr_t uuid, fio_protocol_s *pr) {
410
424
  REDIS_READ_BUFFER - internal->buf_pos);
411
425
  if (i <= 0)
412
426
  return;
427
+
413
428
  internal->buf_pos += i;
414
429
  i = resp_parse(&internal->parser, buf, internal->buf_pos);
415
430
  if (i) {
@@ -447,7 +462,7 @@ static void redis_on_close(intptr_t uuid, fio_protocol_s *pr) {
447
462
  "Reconnecting...",
448
463
  (int)getpid());
449
464
  }
450
- r->pub_send = 0;
465
+ r->pub_sent = 0;
451
466
  fio_close(r->sub_data.uuid);
452
467
  redis_free(r);
453
468
  }
@@ -523,19 +538,16 @@ static void redis_on_connect(intptr_t uuid, void *i_) {
523
538
  (redis_commands_s){.cmd_len = r->auth_len, .callback = redis_on_auth};
524
539
  memcpy(cmd->cmd, r->auth, r->auth_len);
525
540
  fio_lock(&r->lock);
541
+ r->pub_sent = 0;
526
542
  fio_ls_embd_unshift(&r->queue, &cmd->node);
543
+ redis_send_next_command_unsafe(r);
544
+ fio_unlock(&r->lock);
545
+ } else {
546
+ fio_lock(&r->lock);
547
+ r->pub_sent = 0;
548
+ redis_send_next_command_unsafe(r);
527
549
  fio_unlock(&r->lock);
528
550
  }
529
- fio_lock(&r->lock);
530
- FIO_LS_EMBD_FOR(&r->queue, node) {
531
- redis_commands_s *cmd = FIO_LS_EMBD_OBJ(redis_commands_s, node, node);
532
- FIO_LOG_DEBUG("(%d) Sending (%zu bytes):\n%s\n", getpid(), cmd->cmd_len,
533
- cmd->cmd);
534
- fio_write2(uuid, .data.buffer = cmd->cmd, .length = cmd->cmd_len,
535
- .after.dealloc = FIO_DEALLOC_NOOP);
536
- }
537
- r->pub_send = 1;
538
- fio_unlock(&r->lock);
539
551
  FIO_LOG_INFO("(redis %d) publication connection established.",
540
552
  (int)getpid());
541
553
  }
@@ -557,7 +569,9 @@ static void redis_on_connect_failed(intptr_t uuid, void *i_) {
557
569
  static void redis_connect(void *r_, void *i_) {
558
570
  redis_engine_s *r = r_;
559
571
  struct redis_engine_internal_s *i = i_;
572
+ fio_lock(&r->lock_connection);
560
573
  if (r->flag == 0 || i->uuid != -1 || !fio_is_running()) {
574
+ fio_unlock(&r->lock_connection);
561
575
  redis_free(r);
562
576
  return;
563
577
  }
@@ -565,6 +579,7 @@ static void redis_connect(void *r_, void *i_) {
565
579
  i->uuid = fio_connect(.address = r->address, .port = r->port,
566
580
  .on_connect = redis_on_connect, .udata = i,
567
581
  .on_fail = redis_on_connect_failed);
582
+ fio_unlock(&r->lock_connection);
568
583
  }
569
584
 
570
585
  /* *****************************************************************************
@@ -714,7 +729,7 @@ static void redis_forward_reply(fio_pubsub_engine_s *e, FIOBJ reply,
714
729
  }
715
730
  int32_t pid = (int32_t)fio_str2u32(data + 24);
716
731
  FIOBJ rp = fiobj_obj2json(reply, 0);
717
- fio_publish(.filter = (-10 - pid), .channel.data = (char *)data,
732
+ fio_publish(.filter = (-10 - (int32_t)pid), .channel.data = (char *)data,
718
733
  .channel.len = 28, .message = fiobj_obj2cstr(rp), .is_json = 1);
719
734
  fiobj_free(rp);
720
735
  }
@@ -895,13 +910,16 @@ FIO_IGNORE_MACRO(struct redis_engine_create_args args) {
895
910
  .cmd_reply =
896
911
  fio_subscribe(.filter = -10 - (uint32_t)getpid(), .udata1 = r,
897
912
  .on_message = redis_on_internal_reply),
898
- .address = ((char *)(r + 1) + 0),
899
- .port = ((char *)(r + 1) + args.address.len + 1),
900
- .auth = ((char *)(r + 1) + args.address.len + args.port.len + 2),
913
+ .address = ((char *)(r + 1) + (REDIS_READ_BUFFER * 2)),
914
+ .port =
915
+ ((char *)(r + 1) + (REDIS_READ_BUFFER * 2) + args.address.len + 1),
916
+ .auth = ((char *)(r + 1) + (REDIS_READ_BUFFER * 2) + args.address.len +
917
+ args.port.len + 2),
901
918
  .auth_len = args.auth.len,
902
919
  .ref = 1,
903
920
  .queue = FIO_LS_INIT(r->queue),
904
921
  .lock = FIO_LOCK_INIT,
922
+ .lock_connection = FIO_LOCK_INIT,
905
923
  .ping_int = args.ping_interval,
906
924
  .flag = 1,
907
925
  };
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.7.20'.freeze
2
+ VERSION = '0.7.21'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iodine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.20
4
+ version: 0.7.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-31 00:00:00.000000000 Z
11
+ date: 2019-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -220,7 +220,7 @@ licenses:
220
220
  - MIT
221
221
  metadata:
222
222
  allowed_push_host: https://rubygems.org
223
- post_install_message: 'Thank you for installing Iodine 0.7.20.
223
+ post_install_message: 'Thank you for installing Iodine 0.7.21.
224
224
 
225
225
  '
226
226
  rdoc_options: []