polyphony 0.36 → 0.38
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|