rage-iodine 5.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e2925f48b74a97ff3431fc421ebd451c1f8d4befd701ac454ceb0bb8ed2ae82
4
- data.tar.gz: 6c101cf70146f67794adc91ca9eee8cfade412b27bbed04d2c9937e378f25fa8
3
+ metadata.gz: b9b70a5de57c61bdbbd996b844305eb1c0f05f7ca489df818df57147f77bcdd4
4
+ data.tar.gz: '095e078c74ab42347353278e6cb2fd82ca3b5fe582b2d37a835673b06575f386'
5
5
  SHA512:
6
- metadata.gz: bcfba0ed6461dad2478e3f35b1dc2246046d872b6159bac5f93651f7ce3fa74ef2ee86e90727e930bb48514a7266844d9eb616af253f2aef30d92646b65fe06b
7
- data.tar.gz: 2c1fa87406f4f249551addeb72d59231684552bdc5fde2ed55539851afe9b14349497f7cc8e0dfa1969f71668e24b93d1cc591cc5a2e3d560e2b4abd67e56c7b
6
+ metadata.gz: 18dbb21c7678eff317996415f0f1d51e511a5c54c4184cab6a39f85c0f708d99f471daa0c3702ddf850c3273e7588eaee4847e317c6a25d3a8d72fd2cfad47a2
7
+ data.tar.gz: 2e0ec6b84cca4ae1ae0db795eb509082129483b896fbd5caed4ffc8887bb99451c91a49013b56f4cf45a213c720e34b09cef258812900003ea5381eab7658637
data/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ 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
+
9
13
  #### Change log v.5.8.0 (2026-10-09)
10
14
 
11
15
  **Update**: Encode parameters as UTF-8
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
- while (fio_ch_set_count(&fio_postoffice.patterns.channels)) {
7661
- channel_s *ch = fio_ch_set_last(&fio_postoffice.patterns.channels);
7662
- while (fio_ls_embd_any(&ch->subscriptions)) {
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;
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '5.8.0'.freeze
2
+ VERSION = '5.9.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: 5.8.0
4
+ version: 5.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev