polyphony 0.36 → 0.38
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 +9 -0
- data/Gemfile +0 -11
- data/Gemfile.lock +1 -3
- data/Rakefile +4 -0
- data/TODO.md +12 -10
- data/docs/index.md +2 -1
- data/examples/core/xx-fork-cleanup.rb +22 -0
- data/ext/gyro/async.c +27 -13
- data/ext/gyro/child.c +29 -15
- data/ext/gyro/fiber.c +3 -1
- data/ext/gyro/gyro.c +0 -6
- data/ext/gyro/gyro.h +6 -0
- data/ext/gyro/io.c +24 -9
- data/ext/gyro/queue.c +21 -21
- data/ext/gyro/selector.c +23 -0
- data/ext/gyro/signal.c +24 -9
- data/ext/gyro/thread.c +12 -2
- data/ext/gyro/timer.c +33 -18
- data/lib/polyphony.rb +27 -36
- data/lib/polyphony/adapters/fs.rb +1 -4
- data/lib/polyphony/adapters/process.rb +29 -25
- data/lib/polyphony/adapters/trace.rb +129 -124
- data/lib/polyphony/core/channel.rb +36 -36
- data/lib/polyphony/core/exceptions.rb +29 -29
- data/lib/polyphony/core/global_api.rb +92 -91
- data/lib/polyphony/core/resource_pool.rb +84 -84
- data/lib/polyphony/core/sync.rb +17 -17
- data/lib/polyphony/core/thread_pool.rb +49 -37
- data/lib/polyphony/core/throttler.rb +25 -25
- data/lib/polyphony/extensions/core.rb +3 -3
- data/lib/polyphony/extensions/fiber.rb +269 -267
- data/lib/polyphony/extensions/openssl.rb +1 -1
- data/lib/polyphony/extensions/socket.rb +2 -1
- data/lib/polyphony/extensions/thread.rb +3 -3
- data/lib/polyphony/net.rb +71 -67
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +0 -3
- data/test/stress.rb +17 -12
- data/test/test_thread.rb +1 -0
- data/test/test_thread_pool.rb +2 -2
- data/test/test_throttler.rb +0 -1
- metadata +3 -16
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: b952f96f313866e5b61e200093fcb1eb8111b2d48bb2a736e36b62f06772786c
         | 
| 4 | 
            +
              data.tar.gz: 03ffbc7481d3e20cfd5d50cc0c7e1e28749da15a6c9d65c89e83a0370b61b2d2
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 8fb34d135a0ab50a3e3ae722dd3f9ae70ba8ee83534c199f98611f5fa273b424fcedab548929a2dedcdaddec73a9aa6b652fa97a924dd5400155cf57a1cdcaf0
         | 
| 7 | 
            +
              data.tar.gz: caacb6a006f52abf888a9f4a3f1ef2c917a73422abaf1cba7d1ae1b0c7db07a3bc62a5a6b6abbe22e46fd6e679e82d7a048ec2d9ac7ec7dee54453600c688597
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,12 @@ | |
| 1 | 
            +
            ## 0.38 2020-04-13
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Fix post-fork segfault if parent process has multiple threads with active watchers
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ## 0.37 2020-04-07
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Explicitly kill threads on exit to prevent possible segfault
         | 
| 8 | 
            +
            * Remove Modulation dependency
         | 
| 9 | 
            +
             | 
| 1 10 | 
             
            ## 0.36 2020-03-31
         | 
| 2 11 |  | 
| 3 12 | 
             
            * More docs
         | 
    
        data/Gemfile
    CHANGED
    
    | @@ -1,14 +1,3 @@ | |
| 1 1 | 
             
            source 'https://rubygems.org'
         | 
| 2 2 |  | 
| 3 3 | 
             
            gemspec
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            # gem "jekyll", "~> 3.8.6"
         | 
| 6 | 
            -
            # gem "jekyll-remote-theme"
         | 
| 7 | 
            -
            # gem "jekyll-seo-tag"
         | 
| 8 | 
            -
            # gem "just-the-docs"
         | 
| 9 | 
            -
             | 
| 10 | 
            -
            # # gem "github-pages", group: :jekyll_plugins
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            # group :jekyll_plugins do
         | 
| 13 | 
            -
            #   gem "jekyll-feed", "~> 0.6"
         | 
| 14 | 
            -
            # end
         | 
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,8 +1,7 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                polyphony (0. | 
| 5 | 
            -
                  modulation (~> 1.0)
         | 
| 4 | 
            +
                polyphony (0.38)
         | 
| 6 5 |  | 
| 7 6 | 
             
            GEM
         | 
| 8 7 | 
             
              remote: https://rubygems.org/
         | 
| @@ -73,7 +72,6 @@ GEM | |
| 73 72 | 
             
                  builder
         | 
| 74 73 | 
             
                  minitest (>= 5.0)
         | 
| 75 74 | 
             
                  ruby-progressbar
         | 
| 76 | 
            -
                modulation (1.0)
         | 
| 77 75 | 
             
                multi_xml (0.6.0)
         | 
| 78 76 | 
             
                parallel (1.19.1)
         | 
| 79 77 | 
             
                parser (2.7.0.2)
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/TODO.md
    CHANGED
    
    | @@ -32,7 +32,11 @@ | |
| 32 32 | 
             
              Fiber.current.add_child_fiber(t.main_fiber)
         | 
| 33 33 | 
             
              ```
         | 
| 34 34 |  | 
| 35 | 
            -
             | 
| 35 | 
            +
             | 
| 36 | 
            +
             | 
| 37 | 
            +
             | 
| 38 | 
            +
             | 
| 39 | 
            +
            ## 0.40 Some more API work, more docs
         | 
| 36 40 |  | 
| 37 41 | 
             
            - Debugging
         | 
| 38 42 | 
             
              - Eat your own dogfood: need a good tool to check what's going on when some
         | 
| @@ -142,17 +146,15 @@ | |
| 142 146 | 
             
            - Docs
         | 
| 143 147 | 
             
              - landing page:
         | 
| 144 148 | 
             
                - links to the interesting stuff
         | 
| 145 | 
            -
                  - concurrency overview
         | 
| 146 | 
            -
                  - faq
         | 
| 147 149 | 
             
                  - benchmarks
         | 
| 148 150 | 
             
              - explain difference between `sleep` and `suspend`
         | 
| 149 | 
            -
              - add explanation about async vs sync
         | 
| 151 | 
            +
              - add explanation about async vs sync, blocking vs non-blocking
         | 
| 150 152 | 
             
              - discuss using `snooze` for ensuring responsiveness when executing CPU-bound work
         | 
| 151 153 |  | 
| 152 154 | 
             
            - Check why first call to `#sleep` returns too early in tests. Check the
         | 
| 153 155 | 
             
              sleep behaviour in a spawned thread.
         | 
| 154 156 |  | 
| 155 | 
            -
            ## 0. | 
| 157 | 
            +
            ## 0.41 Sinatra / Sidekiq
         | 
| 156 158 |  | 
| 157 159 | 
             
            - sintra app with database access (postgresql)
         | 
| 158 160 |  | 
| @@ -162,13 +164,13 @@ | |
| 162 164 | 
             
              - test performance
         | 
| 163 165 | 
             
              - proceed from there
         | 
| 164 166 |  | 
| 165 | 
            -
            ## 0. | 
| 167 | 
            +
            ## 0.42 Testing && Docs
         | 
| 166 168 |  | 
| 167 169 | 
             
            - Pull out redis/postgres code, put into new `polyphony-xxx` gems
         | 
| 168 170 |  | 
| 169 | 
            -
            ## 0. | 
| 171 | 
            +
            ## 0.43 Integration
         | 
| 170 172 |  | 
| 171 | 
            -
            ## 0. | 
| 173 | 
            +
            ## 0.44 Real IO#gets and IO#read
         | 
| 172 174 |  | 
| 173 175 | 
             
            - More tests
         | 
| 174 176 | 
             
            - Implement some basic stuff missing:
         | 
| @@ -178,11 +180,11 @@ | |
| 178 180 | 
             
              - `IO.foreach`
         | 
| 179 181 | 
             
              - `Process.waitpid`
         | 
| 180 182 |  | 
| 181 | 
            -
            ## 0. | 
| 183 | 
            +
            ## 0.45 Rails
         | 
| 182 184 |  | 
| 183 185 | 
             
            - Rails?
         | 
| 184 186 |  | 
| 185 | 
            -
            ## 0. | 
| 187 | 
            +
            ## 0.46 DNS
         | 
| 186 188 |  | 
| 187 189 | 
             
            ### DNS client
         | 
| 188 190 |  | 
    
        data/docs/index.md
    CHANGED
    
    | @@ -14,8 +14,9 @@ implements a comprehensive | |
| 14 14 | 
             
            using [libev](https://github.com/enki/libev) as a high-performance event reactor
         | 
| 15 15 | 
             
            for I/O, timers, and other asynchronous events.
         | 
| 16 16 |  | 
| 17 | 
            -
            [FAQ](faq){: .btn .btn-green .text-gamma }
         | 
| 18 17 | 
             
            [Take the tutorial](getting-started/tutorial){: .btn .btn-blue .text-gamma }
         | 
| 18 | 
            +
            [Main Concepts](main-concepts/concurrency/){: .btn .btn-green .text-gamma }
         | 
| 19 | 
            +
            [FAQ](faq){: .btn .btn-green .text-gamma }
         | 
| 19 20 | 
             
            [Source code](https://github.com/digital-fabric/polyphony){: .btn .btn-purple .text-gamma target="_blank" }
         | 
| 20 21 | 
             
            {: .mt-6 .h-align-center }
         | 
| 21 22 |  | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'bundler/setup'
         | 
| 4 | 
            +
            require 'polyphony'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Exception.__disable_sanitized_backtrace__ = true
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            t = Thread.new do
         | 
| 9 | 
            +
              async = Gyro::Async.new
         | 
| 10 | 
            +
              spin { async.await }
         | 
| 11 | 
            +
              sleep 100
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            sleep 0.5
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            Polyphony.fork do
         | 
| 17 | 
            +
              puts "forked #{Process.pid}"
         | 
| 18 | 
            +
              sleep 1
         | 
| 19 | 
            +
              puts "done sleeping"
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            sleep 50
         | 
    
        data/ext/gyro/async.c
    CHANGED
    
    | @@ -27,11 +27,15 @@ static void Gyro_Async_mark(void *ptr) { | |
| 27 27 |  | 
| 28 28 | 
             
            static void Gyro_Async_free(void *ptr) {
         | 
| 29 29 | 
             
              struct Gyro_Async *async = ptr;
         | 
| 30 | 
            -
               | 
| 31 | 
            -
                 | 
| 32 | 
            -
             | 
| 30 | 
            +
              switch (async->active) {
         | 
| 31 | 
            +
                case GYRO_WATCHER_POST_FORK:
         | 
| 32 | 
            +
                  return;
         | 
| 33 | 
            +
                case 1:
         | 
| 34 | 
            +
                  ev_clear_pending(async->ev_loop, &async->ev_async);
         | 
| 35 | 
            +
                  ev_async_stop(async->ev_loop, &async->ev_async);
         | 
| 36 | 
            +
                default:
         | 
| 37 | 
            +
                  xfree(async);
         | 
| 33 38 | 
             
              }
         | 
| 34 | 
            -
              xfree(async);
         | 
| 35 39 | 
             
            }
         | 
| 36 40 |  | 
| 37 41 | 
             
            static size_t Gyro_Async_size(const void *ptr) {
         | 
| @@ -49,7 +53,7 @@ static VALUE Gyro_Async_allocate(VALUE klass) { | |
| 49 53 | 
             
              return TypedData_Wrap_Struct(klass, &Gyro_Async_type, async);
         | 
| 50 54 | 
             
            }
         | 
| 51 55 |  | 
| 52 | 
            -
            inline void  | 
| 56 | 
            +
            inline void async_activate(struct Gyro_Async *async) {
         | 
| 53 57 | 
             
              if (async->active) return;
         | 
| 54 58 |  | 
| 55 59 | 
             
              async->active = 1;
         | 
| @@ -60,7 +64,7 @@ inline void Gyro_Async_activate(struct Gyro_Async *async) { | |
| 60 64 | 
             
              ev_async_start(async->ev_loop, &async->ev_async);
         | 
| 61 65 | 
             
            }
         | 
| 62 66 |  | 
| 63 | 
            -
            inline void  | 
| 67 | 
            +
            inline void async_deactivate(struct Gyro_Async *async) {
         | 
| 64 68 | 
             
              if (!async->active) return;
         | 
| 65 69 |  | 
| 66 70 | 
             
              ev_async_stop(async->ev_loop, &async->ev_async);
         | 
| @@ -76,7 +80,7 @@ void Gyro_Async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, int | |
| 76 80 | 
             
              struct Gyro_Async *async = (struct Gyro_Async*)ev_async;
         | 
| 77 81 |  | 
| 78 82 | 
             
              Fiber_make_runnable(async->fiber, async->value);
         | 
| 79 | 
            -
               | 
| 83 | 
            +
              async_deactivate(async);
         | 
| 80 84 | 
             
            }
         | 
| 81 85 |  | 
| 82 86 | 
             
            #define GetGyro_Async(obj, async) \
         | 
| @@ -117,22 +121,31 @@ VALUE Gyro_Async_await(VALUE self) { | |
| 117 121 | 
             
              struct Gyro_Async *async;
         | 
| 118 122 | 
             
              GetGyro_Async(self, async);
         | 
| 119 123 |  | 
| 120 | 
            -
               | 
| 124 | 
            +
              async_activate(async);
         | 
| 121 125 | 
             
              VALUE ret = Gyro_switchpoint();
         | 
| 122 | 
            -
               | 
| 126 | 
            +
              async_deactivate(async);
         | 
| 123 127 |  | 
| 124 128 | 
             
              TEST_RESUME_EXCEPTION(ret);
         | 
| 125 129 | 
             
              RB_GC_GUARD(ret);
         | 
| 126 130 | 
             
              return ret;
         | 
| 127 131 | 
             
            }
         | 
| 128 132 |  | 
| 133 | 
            +
            VALUE Gyro_Async_deactivate_post_fork(VALUE self) {
         | 
| 134 | 
            +
              struct Gyro_Async *async;
         | 
| 135 | 
            +
              GetGyro_Async(self, async);
         | 
| 136 | 
            +
             | 
| 137 | 
            +
              if (async->active)
         | 
| 138 | 
            +
                async->active = GYRO_WATCHER_POST_FORK;
         | 
| 139 | 
            +
              return self;
         | 
| 140 | 
            +
            }
         | 
| 141 | 
            +
             | 
| 129 142 | 
             
            VALUE Gyro_Async_await_no_raise(VALUE self) {
         | 
| 130 143 | 
             
              struct Gyro_Async *async;
         | 
| 131 144 | 
             
              GetGyro_Async(self, async);
         | 
| 132 145 |  | 
| 133 | 
            -
               | 
| 146 | 
            +
              async_activate(async);
         | 
| 134 147 | 
             
              VALUE ret = Gyro_switchpoint();
         | 
| 135 | 
            -
               | 
| 148 | 
            +
              async_deactivate(async);
         | 
| 136 149 |  | 
| 137 150 | 
             
              RB_GC_GUARD(ret);
         | 
| 138 151 | 
             
              return ret;
         | 
| @@ -143,6 +156,7 @@ void Init_Gyro_Async() { | |
| 143 156 | 
             
              rb_define_alloc_func(cGyro_Async, Gyro_Async_allocate);
         | 
| 144 157 |  | 
| 145 158 | 
             
              rb_define_method(cGyro_Async, "initialize", Gyro_Async_initialize, 0);
         | 
| 146 | 
            -
              rb_define_method(cGyro_Async, "signal", Gyro_Async_signal, -1);
         | 
| 147 159 | 
             
              rb_define_method(cGyro_Async, "await", Gyro_Async_await, 0);
         | 
| 148 | 
            -
             | 
| 160 | 
            +
              rb_define_method(cGyro_Async, "deactivate_post_fork", Gyro_Async_deactivate_post_fork, 0);
         | 
| 161 | 
            +
              rb_define_method(cGyro_Async, "signal", Gyro_Async_signal, -1);
         | 
| 162 | 
            +
            }
         | 
    
        data/ext/gyro/child.c
    CHANGED
    
    | @@ -24,11 +24,15 @@ static void Gyro_Child_mark(void *ptr) { | |
| 24 24 |  | 
| 25 25 | 
             
            static void Gyro_Child_free(void *ptr) {
         | 
| 26 26 | 
             
              struct Gyro_Child *child = ptr;
         | 
| 27 | 
            -
               | 
| 28 | 
            -
                 | 
| 29 | 
            -
             | 
| 27 | 
            +
              switch (child->active) {
         | 
| 28 | 
            +
                case GYRO_WATCHER_POST_FORK:
         | 
| 29 | 
            +
                  return;
         | 
| 30 | 
            +
                case 1:
         | 
| 31 | 
            +
                  ev_clear_pending(child->ev_loop, &child->ev_child);
         | 
| 32 | 
            +
                  ev_child_stop(child->ev_loop, &child->ev_child);
         | 
| 33 | 
            +
                default:
         | 
| 34 | 
            +
                  xfree(child);
         | 
| 30 35 | 
             
              }
         | 
| 31 | 
            -
              xfree(child);
         | 
| 32 36 | 
             
            }
         | 
| 33 37 |  | 
| 34 38 | 
             
            static size_t Gyro_Child_size(const void *ptr) {
         | 
| @@ -46,7 +50,7 @@ static VALUE Gyro_Child_allocate(VALUE klass) { | |
| 46 50 | 
             
              return TypedData_Wrap_Struct(klass, &Gyro_Child_type, child);
         | 
| 47 51 | 
             
            }
         | 
| 48 52 |  | 
| 49 | 
            -
            inline void  | 
| 53 | 
            +
            inline void child_activate(struct Gyro_Child *child) {
         | 
| 50 54 | 
             
              if (child->active) return;
         | 
| 51 55 |  | 
| 52 56 | 
             
              child->active = 1;
         | 
| @@ -57,7 +61,7 @@ inline void Gyro_Child_activate(struct Gyro_Child *child) { | |
| 57 61 | 
             
              ev_child_start(child->ev_loop, &child->ev_child);
         | 
| 58 62 | 
             
            }
         | 
| 59 63 |  | 
| 60 | 
            -
            inline void  | 
| 64 | 
            +
            inline void child_deactivate(struct Gyro_Child *child) {
         | 
| 61 65 | 
             
              if (!child->active) return;
         | 
| 62 66 |  | 
| 63 67 | 
             
              ev_child_stop(child->ev_loop, &child->ev_child);
         | 
| @@ -82,7 +86,7 @@ void Gyro_Child_callback(struct ev_loop *ev_loop, struct ev_child *ev_child, int | |
| 82 86 | 
             
              VALUE resume_value = Gyro_Child_resume_value(ev_child);
         | 
| 83 87 | 
             
              Fiber_make_runnable(child->fiber, resume_value);
         | 
| 84 88 |  | 
| 85 | 
            -
               | 
| 89 | 
            +
              child_deactivate(child);
         | 
| 86 90 | 
             
            }
         | 
| 87 91 |  | 
| 88 92 | 
             
            #define GetGyro_Child(obj, child) \
         | 
| @@ -93,12 +97,12 @@ static VALUE Gyro_Child_initialize(VALUE self, VALUE pid) { | |
| 93 97 |  | 
| 94 98 | 
             
              GetGyro_Child(self, child);
         | 
| 95 99 |  | 
| 96 | 
            -
              child->self | 
| 97 | 
            -
              child->fiber | 
| 98 | 
            -
              child->selector | 
| 99 | 
            -
              child->pid | 
| 100 | 
            -
              child->active | 
| 101 | 
            -
              child->ev_loop | 
| 100 | 
            +
              child->self       = self;
         | 
| 101 | 
            +
              child->fiber      = Qnil;
         | 
| 102 | 
            +
              child->selector   = Qnil;
         | 
| 103 | 
            +
              child->pid        = NUM2INT(pid);
         | 
| 104 | 
            +
              child->active     = 0;
         | 
| 105 | 
            +
              child->ev_loop    = 0;
         | 
| 102 106 |  | 
| 103 107 | 
             
              ev_child_init(&child->ev_child, Gyro_Child_callback, child->pid, 0);
         | 
| 104 108 |  | 
| @@ -109,19 +113,29 @@ static VALUE Gyro_Child_await(VALUE self) { | |
| 109 113 | 
             
              struct Gyro_Child *child;
         | 
| 110 114 | 
             
              GetGyro_Child(self, child);
         | 
| 111 115 |  | 
| 112 | 
            -
               | 
| 116 | 
            +
              child_activate(child);
         | 
| 113 117 | 
             
              VALUE ret = Gyro_switchpoint();
         | 
| 114 | 
            -
               | 
| 118 | 
            +
              child_deactivate(child);
         | 
| 115 119 |  | 
| 116 120 | 
             
              TEST_RESUME_EXCEPTION(ret);
         | 
| 117 121 | 
             
              RB_GC_GUARD(ret);
         | 
| 118 122 | 
             
              return ret;
         | 
| 119 123 | 
             
            }
         | 
| 120 124 |  | 
| 125 | 
            +
            VALUE Gyro_Child_deactivate_post_fork(VALUE self) {
         | 
| 126 | 
            +
              struct Gyro_Child *child;
         | 
| 127 | 
            +
              GetGyro_Child(self, child);
         | 
| 128 | 
            +
             | 
| 129 | 
            +
              if (child->active)
         | 
| 130 | 
            +
                child->active = GYRO_WATCHER_POST_FORK;
         | 
| 131 | 
            +
              return self;
         | 
| 132 | 
            +
            }
         | 
| 133 | 
            +
             | 
| 121 134 | 
             
            void Init_Gyro_Child() {
         | 
| 122 135 | 
             
              cGyro_Child = rb_define_class_under(mGyro, "Child", rb_cData);
         | 
| 123 136 | 
             
              rb_define_alloc_func(cGyro_Child, Gyro_Child_allocate);
         | 
| 124 137 |  | 
| 125 138 | 
             
              rb_define_method(cGyro_Child, "initialize", Gyro_Child_initialize, 1);
         | 
| 126 139 | 
             
              rb_define_method(cGyro_Child, "await", Gyro_Child_await, 0);
         | 
| 140 | 
            +
              rb_define_method(cGyro_Child, "deactivate_post_fork", Gyro_Child_deactivate_post_fork, 0);
         | 
| 127 141 | 
             
            }
         | 
    
        data/ext/gyro/fiber.c
    CHANGED
    
    | @@ -71,7 +71,9 @@ void Fiber_make_runnable(VALUE fiber, VALUE value) { | |
| 71 71 | 
             
                Thread_schedule_fiber(thread, fiber, value);
         | 
| 72 72 | 
             
              }
         | 
| 73 73 | 
             
              else {
         | 
| 74 | 
            -
                rb_warn("No thread set for fiber");
         | 
| 74 | 
            +
                rb_warn("No thread set for fiber (fiber, value, caller):");
         | 
| 75 | 
            +
                VALUE caller = rb_funcall(rb_cObject, rb_intern("caller"), 0);
         | 
| 76 | 
            +
                INSPECT(3, fiber, value, caller);
         | 
| 75 77 | 
             
              }
         | 
| 76 78 | 
             
            }
         | 
| 77 79 |  | 
    
        data/ext/gyro/gyro.c
    CHANGED
    
    | @@ -44,11 +44,6 @@ VALUE Gyro_snooze(VALUE self) { | |
| 44 44 | 
             
              return ret;
         | 
| 45 45 | 
             
            }
         | 
| 46 46 |  | 
| 47 | 
            -
            static VALUE Gyro_post_fork(VALUE self) {
         | 
| 48 | 
            -
              Thread_post_fork(rb_thread_current());
         | 
| 49 | 
            -
              return Qnil;
         | 
| 50 | 
            -
            }
         | 
| 51 | 
            -
             | 
| 52 47 | 
             
            static VALUE Gyro_ref(VALUE self) {
         | 
| 53 48 | 
             
              return Thread_ref(rb_thread_current());
         | 
| 54 49 | 
             
            }
         | 
| @@ -73,7 +68,6 @@ VALUE Gyro_trace(VALUE self, VALUE enabled) { | |
| 73 68 | 
             
            void Init_Gyro() {
         | 
| 74 69 | 
             
              mGyro = rb_define_module("Gyro");
         | 
| 75 70 |  | 
| 76 | 
            -
              rb_define_singleton_method(mGyro, "post_fork", Gyro_post_fork, 0);
         | 
| 77 71 | 
             
              rb_define_singleton_method(mGyro, "ref", Gyro_ref, 0);
         | 
| 78 72 | 
             
              rb_define_singleton_method(mGyro, "unref", Gyro_unref, 0);
         | 
| 79 73 | 
             
              rb_define_singleton_method(mGyro, "trace", Gyro_trace, 1);
         | 
    
        data/ext/gyro/gyro.h
    CHANGED
    
    | @@ -59,6 +59,12 @@ enum { | |
| 59 59 | 
             
              FIBER_STATE_SCHEDULED     = 2
         | 
| 60 60 | 
             
            };
         | 
| 61 61 |  | 
| 62 | 
            +
            // watcher flags
         | 
| 63 | 
            +
            enum {
         | 
| 64 | 
            +
              // a watcher's active field will be set to this after fork
         | 
| 65 | 
            +
              GYRO_WATCHER_POST_FORK = 0xFF
         | 
| 66 | 
            +
            };
         | 
| 67 | 
            +
             | 
| 62 68 | 
             
            VALUE Fiber_auto_async(VALUE self);
         | 
| 63 69 | 
             
            VALUE Fiber_auto_io(VALUE self);
         | 
| 64 70 | 
             
            void Fiber_make_runnable(VALUE fiber, VALUE value);
         | 
    
        data/ext/gyro/io.c
    CHANGED
    
    | @@ -34,11 +34,15 @@ static void Gyro_IO_mark(void *ptr) { | |
| 34 34 |  | 
| 35 35 | 
             
            static void Gyro_IO_free(void *ptr) {
         | 
| 36 36 | 
             
              struct Gyro_IO *io = ptr;
         | 
| 37 | 
            -
               | 
| 38 | 
            -
                 | 
| 39 | 
            -
             | 
| 37 | 
            +
              switch (io->active) {
         | 
| 38 | 
            +
                case GYRO_WATCHER_POST_FORK:
         | 
| 39 | 
            +
                  return;
         | 
| 40 | 
            +
                case 1:
         | 
| 41 | 
            +
                  ev_clear_pending(io->ev_loop, &io->ev_io);
         | 
| 42 | 
            +
                  ev_io_stop(io->ev_loop, &io->ev_io);
         | 
| 43 | 
            +
                default:
         | 
| 44 | 
            +
                  xfree(io);
         | 
| 40 45 | 
             
              }
         | 
| 41 | 
            -
              xfree(io);
         | 
| 42 46 | 
             
            }
         | 
| 43 47 |  | 
| 44 48 | 
             
            static size_t Gyro_IO_size(const void *ptr) {
         | 
| @@ -57,7 +61,7 @@ static VALUE Gyro_IO_allocate(VALUE klass) { | |
| 57 61 | 
             
              return TypedData_Wrap_Struct(klass, &Gyro_IO_type, io);
         | 
| 58 62 | 
             
            }
         | 
| 59 63 |  | 
| 60 | 
            -
            inline void  | 
| 64 | 
            +
            inline void io_activate(struct Gyro_IO *io) {
         | 
| 61 65 | 
             
              if (io->active) return;
         | 
| 62 66 |  | 
| 63 67 | 
             
              io->active = 1;
         | 
| @@ -68,7 +72,7 @@ inline void Gyro_IO_activate(struct Gyro_IO *io) { | |
| 68 72 | 
             
              ev_io_start(io->ev_loop, &io->ev_io);
         | 
| 69 73 | 
             
            }
         | 
| 70 74 |  | 
| 71 | 
            -
            inline void  | 
| 75 | 
            +
            inline void io_deactivate(struct Gyro_IO *io) {
         | 
| 72 76 | 
             
              if (!io->active) return;
         | 
| 73 77 |  | 
| 74 78 | 
             
              ev_io_stop(io->ev_loop, &io->ev_io);
         | 
| @@ -83,7 +87,7 @@ void Gyro_IO_callback(struct ev_loop *ev_loop, struct ev_io *ev_io, int revents) | |
| 83 87 | 
             
              struct Gyro_IO *io = (struct Gyro_IO*)ev_io;
         | 
| 84 88 |  | 
| 85 89 | 
             
              Fiber_make_runnable(io->fiber, Qnil);
         | 
| 86 | 
            -
               | 
| 90 | 
            +
              io_deactivate(io);
         | 
| 87 91 | 
             
            }
         | 
| 88 92 |  | 
| 89 93 | 
             
            static int Gyro_IO_symbol2event_mask(VALUE sym) {
         | 
| @@ -143,15 +147,25 @@ VALUE Gyro_IO_await(VALUE self) { | |
| 143 147 | 
             
              struct Gyro_IO *io;
         | 
| 144 148 | 
             
              GetGyro_IO(self, io);
         | 
| 145 149 |  | 
| 146 | 
            -
               | 
| 150 | 
            +
              io_activate(io);
         | 
| 147 151 | 
             
              VALUE ret = Gyro_switchpoint();
         | 
| 148 | 
            -
               | 
| 152 | 
            +
              io_deactivate(io);
         | 
| 149 153 |  | 
| 150 154 | 
             
              TEST_RESUME_EXCEPTION(ret);
         | 
| 151 155 | 
             
              RB_GC_GUARD(ret);
         | 
| 152 156 | 
             
              return ret;
         | 
| 153 157 | 
             
            }
         | 
| 154 158 |  | 
| 159 | 
            +
            VALUE Gyro_IO_deactivate_post_fork(VALUE self) {
         | 
| 160 | 
            +
              struct Gyro_IO *io;
         | 
| 161 | 
            +
              GetGyro_IO(self, io);
         | 
| 162 | 
            +
             | 
| 163 | 
            +
              if (io->active)
         | 
| 164 | 
            +
                io->active = GYRO_WATCHER_POST_FORK;
         | 
| 165 | 
            +
             | 
| 166 | 
            +
              return self;
         | 
| 167 | 
            +
            }
         | 
| 168 | 
            +
             | 
| 155 169 | 
             
            VALUE Gyro_IO_auto_io(int fd, int events) {
         | 
| 156 170 | 
             
              VALUE watcher = Fiber_auto_io(rb_fiber_current());
         | 
| 157 171 | 
             
              struct Gyro_IO *io;
         | 
| @@ -453,6 +467,7 @@ void Init_Gyro_IO() { | |
| 453 467 |  | 
| 454 468 | 
             
              rb_define_method(cGyro_IO, "initialize", Gyro_IO_initialize, 2);
         | 
| 455 469 | 
             
              rb_define_method(cGyro_IO, "await", Gyro_IO_await, 0);
         | 
| 470 | 
            +
              rb_define_method(cGyro_IO, "deactivate_post_fork", Gyro_IO_deactivate_post_fork, 0);
         | 
| 456 471 |  | 
| 457 472 | 
             
              VALUE cIO = rb_const_get(rb_cObject, rb_intern("IO"));
         | 
| 458 473 | 
             
              // rb_define_method(cIO, "gets", IO_gets, -1);
         |