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);
|