rage-iodine 5.7.0 → 5.9.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 +4 -4
- data/CHANGELOG.md +8 -0
- data/ext/iodine/fio.c +39 -32
- data/ext/iodine/http.c +4 -2
- data/ext/iodine/iodine_helpers.c +2 -2
- data/lib/iodine/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b9b70a5de57c61bdbbd996b844305eb1c0f05f7ca489df818df57147f77bcdd4
|
|
4
|
+
data.tar.gz: '095e078c74ab42347353278e6cb2fd82ca3b5fe582b2d37a835673b06575f386'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 18dbb21c7678eff317996415f0f1d51e511a5c54c4184cab6a39f85c0f708d99f471daa0c3702ddf850c3273e7588eaee4847e317c6a25d3a8d72fd2cfad47a2
|
|
7
|
+
data.tar.gz: 2e0ec6b84cca4ae1ae0db795eb509082129483b896fbd5caed4ffc8887bb99451c91a49013b56f4cf45a213c720e34b09cef258812900003ea5381eab7658637
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,14 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
|
6
6
|
|
|
7
7
|
## Changes:
|
|
8
8
|
|
|
9
|
+
#### Change log v.5.9.0 (2026-10-15)
|
|
10
|
+
|
|
11
|
+
**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.
|
|
12
|
+
|
|
13
|
+
#### Change log v.5.8.0 (2026-10-09)
|
|
14
|
+
|
|
15
|
+
**Update**: Encode parameters as UTF-8
|
|
16
|
+
|
|
9
17
|
#### Change log v.5.7.0 (2026-10-04)
|
|
10
18
|
|
|
11
19
|
**Update**: Refactor parameters parsing
|
data/ext/iodine/fio.c
CHANGED
|
@@ -7644,6 +7644,25 @@ static inline void fio_cluster_inform_root_about_channel(channel_s *ch,
|
|
|
7644
7644
|
/* *****************************************************************************
|
|
7645
7645
|
* Initialization
|
|
7646
7646
|
**************************************************************************** */
|
|
7647
|
+
/* best-effort teardown without fio_unsubscribe: it may free `ch` (and remove
|
|
7648
|
+
* it from the set) while this loop still uses it (#21) */
|
|
7649
|
+
FIO_FUNC void fio_pubsub_at_exit_clear(fio_ch_set_s *channels) {
|
|
7650
|
+
while (fio_ch_set_count(channels)) {
|
|
7651
|
+
channel_s *ch = fio_ch_set_last(channels);
|
|
7652
|
+
while (fio_ls_embd_any(&ch->subscriptions)) {
|
|
7653
|
+
subscription_s *sub =
|
|
7654
|
+
FIO_LS_EMBD_OBJ(subscription_s, node, ch->subscriptions.next);
|
|
7655
|
+
fio_ls_embd_remove(&sub->node);
|
|
7656
|
+
sub->unsubscribed = 1;
|
|
7657
|
+
sub->on_message = NULL;
|
|
7658
|
+
sub->on_unsubscribe = NULL;
|
|
7659
|
+
fio_subscription_free(sub);
|
|
7660
|
+
}
|
|
7661
|
+
fio_ch_set_pop(channels);
|
|
7662
|
+
}
|
|
7663
|
+
fio_ch_set_free(channels);
|
|
7664
|
+
}
|
|
7665
|
+
|
|
7647
7666
|
#ifndef __MINGW32__
|
|
7648
7667
|
static void fio_accept_after_fork(void *ignore) {
|
|
7649
7668
|
/* prevent `accept` backlog in parent */
|
|
@@ -7657,38 +7676,9 @@ static void fio_cluster_at_exit(void *ignore) {
|
|
|
7657
7676
|
/* unlock all */
|
|
7658
7677
|
fio_pubsub_on_fork();
|
|
7659
7678
|
/* clear subscriptions of all types */
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
subscription_s *sub =
|
|
7664
|
-
FIO_LS_EMBD_OBJ(subscription_s, node, ch->subscriptions.next);
|
|
7665
|
-
fio_unsubscribe(sub);
|
|
7666
|
-
}
|
|
7667
|
-
fio_ch_set_pop(&fio_postoffice.patterns.channels);
|
|
7668
|
-
}
|
|
7669
|
-
|
|
7670
|
-
while (fio_ch_set_count(&fio_postoffice.pubsub.channels)) {
|
|
7671
|
-
channel_s *ch = fio_ch_set_last(&fio_postoffice.pubsub.channels);
|
|
7672
|
-
while (fio_ls_embd_any(&ch->subscriptions)) {
|
|
7673
|
-
subscription_s *sub =
|
|
7674
|
-
FIO_LS_EMBD_OBJ(subscription_s, node, ch->subscriptions.next);
|
|
7675
|
-
fio_unsubscribe(sub);
|
|
7676
|
-
}
|
|
7677
|
-
fio_ch_set_pop(&fio_postoffice.pubsub.channels);
|
|
7678
|
-
}
|
|
7679
|
-
|
|
7680
|
-
while (fio_ch_set_count(&fio_postoffice.filters.channels)) {
|
|
7681
|
-
channel_s *ch = fio_ch_set_last(&fio_postoffice.filters.channels);
|
|
7682
|
-
while (fio_ls_embd_any(&ch->subscriptions)) {
|
|
7683
|
-
subscription_s *sub =
|
|
7684
|
-
FIO_LS_EMBD_OBJ(subscription_s, node, ch->subscriptions.next);
|
|
7685
|
-
fio_unsubscribe(sub);
|
|
7686
|
-
}
|
|
7687
|
-
fio_ch_set_pop(&fio_postoffice.filters.channels);
|
|
7688
|
-
}
|
|
7689
|
-
fio_ch_set_free(&fio_postoffice.filters.channels);
|
|
7690
|
-
fio_ch_set_free(&fio_postoffice.patterns.channels);
|
|
7691
|
-
fio_ch_set_free(&fio_postoffice.pubsub.channels);
|
|
7679
|
+
fio_pubsub_at_exit_clear(&fio_postoffice.patterns.channels);
|
|
7680
|
+
fio_pubsub_at_exit_clear(&fio_postoffice.pubsub.channels);
|
|
7681
|
+
fio_pubsub_at_exit_clear(&fio_postoffice.filters.channels);
|
|
7692
7682
|
|
|
7693
7683
|
/* clear engines */
|
|
7694
7684
|
FIO_PUBSUB_DEFAULT = FIO_PUBSUB_CLUSTER;
|
|
@@ -12092,6 +12082,23 @@ FIO_FUNC void fio_pubsub_test(void) {
|
|
|
12092
12082
|
++expect;
|
|
12093
12083
|
fio_defer_perform();
|
|
12094
12084
|
FIO_ASSERT(counter == expect, "unsubscribe wasn't called for named channel!");
|
|
12085
|
+
|
|
12086
|
+
/* Regression #21: at-exit cleanup must terminate and empty the set, even
|
|
12087
|
+
* with several subscriptions per channel or an already-marked one. */
|
|
12088
|
+
fio_subscribe(.channel = {0, 9, "hang-test"}, .udata1 = &counter,
|
|
12089
|
+
.on_message = fio_pubsub_test_on_message,
|
|
12090
|
+
.on_unsubscribe = fio_pubsub_test_on_unsubscribe);
|
|
12091
|
+
s = fio_subscribe(.channel = {0, 9, "hang-test"}, .udata1 = &counter,
|
|
12092
|
+
.on_message = fio_pubsub_test_on_message,
|
|
12093
|
+
.on_unsubscribe = fio_pubsub_test_on_unsubscribe);
|
|
12094
|
+
FIO_ASSERT(s, "fio_subscribe FAILED for hang-test channel.");
|
|
12095
|
+
fio_trylock(&s->unsubscribed);
|
|
12096
|
+
fio_pubsub_at_exit_clear(&fio_postoffice.pubsub.channels);
|
|
12097
|
+
FIO_ASSERT(!fio_ch_set_count(&fio_postoffice.pubsub.channels),
|
|
12098
|
+
"at-exit cleanup left channels behind (#21)");
|
|
12099
|
+
fio_defer_perform();
|
|
12100
|
+
FIO_ASSERT(counter == expect, "at-exit cleanup shouldn't call callbacks!");
|
|
12101
|
+
|
|
12095
12102
|
fio_data->is_worker = 0;
|
|
12096
12103
|
fio_data->active = 0;
|
|
12097
12104
|
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,
|
|
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,
|
|
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
|
/* *****************************************************************************
|
data/ext/iodine/iodine_helpers.c
CHANGED
|
@@ -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 =
|
|
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 =
|
|
293
|
+
value = rb_enc_str_new(NULL, 0, IodineUTF8Encoding);
|
|
294
294
|
} else {
|
|
295
295
|
value = Qnil;
|
|
296
296
|
}
|
data/lib/iodine/version.rb
CHANGED