rage-iodine 6.1.0 → 6.3.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: 6096c74f8f76040521a3d8d977be278e9da518a65e3a5dedd7f715ebcf8c8ae7
4
- data.tar.gz: 365e0c9732780d5672f3ca2e9b4ca23cfe1a954cb24a2ec58d013e2a59081e1f
3
+ metadata.gz: 5bf4dfb83b39ffd7e2c88b535342d69b9ba6492dd80381e747c7f8909025b5c1
4
+ data.tar.gz: 7d2e6bdafc532d94b296fb0743cfe832942421ecfa8ddab78a21f7f3e5c50f1e
5
5
  SHA512:
6
- metadata.gz: 8a8fc73f923a749da72f025797613c4036f79e1405e4f8791b8276a8629cdb511d8f9ec40e1b56087f5bc049058351fd7d126372a179a228de4de77aa3a295b9
7
- data.tar.gz: 19526c5ba722bebb05e18cb4125f7cf46acd8c129f5766709888718fe45f6876065fb9fd34f5c98ec8ccfa86a962418b607e63fbf4c249bbc9419ce6cb1ef053
6
+ metadata.gz: 9989075b63db053de7dd6678cb317aef338c9150acfb88da70a8cf0d77f13acd1b6c5aff12cadf212a85534f84832fb9b2af71580f88eb5fcc1de065f2d3b015
7
+ data.tar.gz: bd74de0e0b28d2b035cc3df029ea7930ef57221ab4a443d88df873421ce4634567cb7e2fb06cfaec9a3e878feacb0d70541c6710191855c73b6d55c6173daf10
@@ -4,6 +4,7 @@ on:
4
4
  push:
5
5
  branches:
6
6
  - master
7
+ - release/*
7
8
  paths:
8
9
  - lib/iodine/version.rb
9
10
 
data/CHANGELOG.md CHANGED
@@ -6,10 +6,26 @@ Please notice that this change log contains changes for upcoming releases as wel
6
6
 
7
7
  ## Changes:
8
8
 
9
+ #### Change log v.6.3.0 (2026-10-23)
10
+
11
+ **Fix**: Fix `rack.input` buffer coderange
12
+
13
+ #### Change log v.5.9.0/v.6.2.0 (2026-10-15)
14
+
15
+ **Fix**: Prevent process hang on exit caused by a use-after-free in pub/sub teardown (`fio_cluster_at_exit` read a channel freed by `fio_unsubscribe` of its last subscription; it now performs a bounded best-effort cleanup instead). See #21.
16
+
17
+ #### Change log v.5.8.0 (2026-10-09)
18
+
19
+ **Update**: Encode parameters as UTF-8
20
+
9
21
  #### Change log v.6.1.0 (2026-10-04)
10
22
 
11
23
  **Update**: Refactor parameters parsing
12
24
 
25
+ #### Change log v.5.7.0 (2026-10-04)
26
+
27
+ **Update**: Refactor parameters parsing
28
+
13
29
  #### Change log v.6.0.0 (2026-09-06)
14
30
 
15
31
  **Update**: Update scheduler `read`/`write` hooks
data/ext/iodine/fio.c CHANGED
@@ -7658,6 +7658,25 @@ static inline void fio_cluster_inform_root_about_channel(channel_s *ch,
7658
7658
  /* *****************************************************************************
7659
7659
  * Initialization
7660
7660
  **************************************************************************** */
7661
+ /* best-effort teardown without fio_unsubscribe: it may free `ch` (and remove
7662
+ * it from the set) while this loop still uses it (#21) */
7663
+ FIO_FUNC void fio_pubsub_at_exit_clear(fio_ch_set_s *channels) {
7664
+ while (fio_ch_set_count(channels)) {
7665
+ channel_s *ch = fio_ch_set_last(channels);
7666
+ while (fio_ls_embd_any(&ch->subscriptions)) {
7667
+ subscription_s *sub =
7668
+ FIO_LS_EMBD_OBJ(subscription_s, node, ch->subscriptions.next);
7669
+ fio_ls_embd_remove(&sub->node);
7670
+ sub->unsubscribed = 1;
7671
+ sub->on_message = NULL;
7672
+ sub->on_unsubscribe = NULL;
7673
+ fio_subscription_free(sub);
7674
+ }
7675
+ fio_ch_set_pop(channels);
7676
+ }
7677
+ fio_ch_set_free(channels);
7678
+ }
7679
+
7661
7680
  #ifndef __MINGW32__
7662
7681
  static void fio_accept_after_fork(void *ignore) {
7663
7682
  /* prevent `accept` backlog in parent */
@@ -7671,38 +7690,9 @@ static void fio_cluster_at_exit(void *ignore) {
7671
7690
  /* unlock all */
7672
7691
  fio_pubsub_on_fork();
7673
7692
  /* clear subscriptions of all types */
7674
- while (fio_ch_set_count(&fio_postoffice.patterns.channels)) {
7675
- channel_s *ch = fio_ch_set_last(&fio_postoffice.patterns.channels);
7676
- while (fio_ls_embd_any(&ch->subscriptions)) {
7677
- subscription_s *sub =
7678
- FIO_LS_EMBD_OBJ(subscription_s, node, ch->subscriptions.next);
7679
- fio_unsubscribe(sub);
7680
- }
7681
- fio_ch_set_pop(&fio_postoffice.patterns.channels);
7682
- }
7683
-
7684
- while (fio_ch_set_count(&fio_postoffice.pubsub.channels)) {
7685
- channel_s *ch = fio_ch_set_last(&fio_postoffice.pubsub.channels);
7686
- while (fio_ls_embd_any(&ch->subscriptions)) {
7687
- subscription_s *sub =
7688
- FIO_LS_EMBD_OBJ(subscription_s, node, ch->subscriptions.next);
7689
- fio_unsubscribe(sub);
7690
- }
7691
- fio_ch_set_pop(&fio_postoffice.pubsub.channels);
7692
- }
7693
-
7694
- while (fio_ch_set_count(&fio_postoffice.filters.channels)) {
7695
- channel_s *ch = fio_ch_set_last(&fio_postoffice.filters.channels);
7696
- while (fio_ls_embd_any(&ch->subscriptions)) {
7697
- subscription_s *sub =
7698
- FIO_LS_EMBD_OBJ(subscription_s, node, ch->subscriptions.next);
7699
- fio_unsubscribe(sub);
7700
- }
7701
- fio_ch_set_pop(&fio_postoffice.filters.channels);
7702
- }
7703
- fio_ch_set_free(&fio_postoffice.filters.channels);
7704
- fio_ch_set_free(&fio_postoffice.patterns.channels);
7705
- fio_ch_set_free(&fio_postoffice.pubsub.channels);
7693
+ fio_pubsub_at_exit_clear(&fio_postoffice.patterns.channels);
7694
+ fio_pubsub_at_exit_clear(&fio_postoffice.pubsub.channels);
7695
+ fio_pubsub_at_exit_clear(&fio_postoffice.filters.channels);
7706
7696
 
7707
7697
  /* clear engines */
7708
7698
  FIO_PUBSUB_DEFAULT = FIO_PUBSUB_CLUSTER;
@@ -12106,6 +12096,23 @@ FIO_FUNC void fio_pubsub_test(void) {
12106
12096
  ++expect;
12107
12097
  fio_defer_perform();
12108
12098
  FIO_ASSERT(counter == expect, "unsubscribe wasn't called for named channel!");
12099
+
12100
+ /* Regression #21: at-exit cleanup must terminate and empty the set, even
12101
+ * with several subscriptions per channel or an already-marked one. */
12102
+ fio_subscribe(.channel = {0, 9, "hang-test"}, .udata1 = &counter,
12103
+ .on_message = fio_pubsub_test_on_message,
12104
+ .on_unsubscribe = fio_pubsub_test_on_unsubscribe);
12105
+ s = fio_subscribe(.channel = {0, 9, "hang-test"}, .udata1 = &counter,
12106
+ .on_message = fio_pubsub_test_on_message,
12107
+ .on_unsubscribe = fio_pubsub_test_on_unsubscribe);
12108
+ FIO_ASSERT(s, "fio_subscribe FAILED for hang-test channel.");
12109
+ fio_trylock(&s->unsubscribed);
12110
+ fio_pubsub_at_exit_clear(&fio_postoffice.pubsub.channels);
12111
+ FIO_ASSERT(!fio_ch_set_count(&fio_postoffice.pubsub.channels),
12112
+ "at-exit cleanup left channels behind (#21)");
12113
+ fio_defer_perform();
12114
+ FIO_ASSERT(counter == expect, "at-exit cleanup shouldn't call callbacks!");
12115
+
12109
12116
  fio_data->is_worker = 0;
12110
12117
  fio_data->active = 0;
12111
12118
  fio_data->workers = 0;
data/ext/iodine/http.c CHANGED
@@ -68,6 +68,7 @@ static VALUE cUploadedFile;
68
68
  static ID create_id;
69
69
  static ID path_id;
70
70
  static rb_encoding *IodineBinaryEncoding;
71
+ static rb_encoding *IodineUTF8Encoding;
71
72
 
72
73
  /* *****************************************************************************
73
74
  Small Helpers
@@ -2010,7 +2011,7 @@ static void http_mime_parser_on_data(http_mime_parser_s *parser, void *name,
2010
2011
  size_t value_len) {
2011
2012
  // for regular values - just add them to params
2012
2013
  if (!filename_len) {
2013
- VALUE r_value = rb_enc_str_new(value, value_len, IodineBinaryEncoding);
2014
+ VALUE r_value = rb_enc_str_new(value, value_len, IodineUTF8Encoding);
2014
2015
  http_add_to_params(http_mime_parser2fio(parser)->params, name, name_len, r_value);
2015
2016
  return;
2016
2017
  }
@@ -2085,7 +2086,7 @@ static void http_mime_parser_on_partial_end(http_mime_parser_s *parser) {
2085
2086
 
2086
2087
  FIOBJ slice = fiobj_data_slice(fio_parser->h->body, fio_parser->partial_offset, fio_parser->partial_length);
2087
2088
  fio_str_info_s s_slice = fiobj_obj2cstr(slice);
2088
- VALUE r_value = rb_enc_str_new(s_slice.data, s_slice.len, IodineBinaryEncoding);
2089
+ VALUE r_value = rb_enc_str_new(s_slice.data, s_slice.len, IodineUTF8Encoding);
2089
2090
  http_add_to_params(fio_parser->params, RSTRING_PTR(fio_parser->partial_name), RSTRING_LEN(fio_parser->partial_name), r_value);
2090
2091
 
2091
2092
  fio_parser->partial_name = Qnil;
@@ -2701,6 +2702,7 @@ void http_init(void) {
2701
2702
  path_id = rb_intern("path");
2702
2703
 
2703
2704
  IodineBinaryEncoding = rb_enc_find("binary");
2705
+ IodineUTF8Encoding = rb_enc_find("UTF-8");
2704
2706
  }
2705
2707
 
2706
2708
  /* *****************************************************************************
@@ -242,7 +242,7 @@ Convert query string into a Ruby object without recursion.
242
242
  */
243
243
  static VALUE build_query_component(char *str, size_t len,
244
244
  uint8_t should_decode) {
245
- VALUE result = rb_str_new(str, len);
245
+ VALUE result = rb_enc_str_new(str, len, IodineUTF8Encoding);
246
246
  if (should_decode) {
247
247
  url_decode_inplace(Qnil, result);
248
248
  }
@@ -290,7 +290,7 @@ static VALUE parse_nested_query_internal(char *str, size_t len) {
290
290
  pair_end - separator - 1,
291
291
  value_should_decode);
292
292
  } else if (key_len > 1 && memchr(key_data + 1, '[', key_len - 1)) {
293
- value = rb_str_new(NULL, 0);
293
+ value = rb_enc_str_new(NULL, 0, IodineUTF8Encoding);
294
294
  } else {
295
295
  value = Qnil;
296
296
  }
@@ -146,6 +146,7 @@ static VALUE rio_read(int argc, VALUE *argv, VALUE self) {
146
146
  } else {
147
147
  // make sure the buffer is binary encoded.
148
148
  rb_enc_associate(buffer, IodineBinaryEncoding);
149
+ rb_str_modify(buffer);
149
150
  if (rb_str_capacity(buffer) < (size_t)buf.len)
150
151
  rb_str_resize(buffer, buf.len);
151
152
  memcpy(RSTRING_PTR(buffer), buf.data, buf.len);
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '6.1.0'.freeze
2
+ VERSION = '6.3.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rage-iodine
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.0
4
+ version: 6.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev