libuv 2.0.12 → 3.0.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/.gitignore +2 -0
- data/README.md +67 -34
- data/lib/libuv.rb +30 -5
- data/lib/libuv/async.rb +16 -10
- data/lib/libuv/check.rb +19 -12
- data/lib/libuv/coroutines.rb +39 -12
- data/lib/libuv/dns.rb +25 -18
- data/lib/libuv/error.rb +2 -0
- data/lib/libuv/ext/ext.rb +28 -36
- data/lib/libuv/ext/platform/darwin_x64.rb +2 -0
- data/lib/libuv/ext/platform/unix.rb +2 -0
- data/lib/libuv/ext/platform/windows.rb +2 -0
- data/lib/libuv/ext/tasks.rb +2 -0
- data/lib/libuv/ext/tasks/mac.rb +2 -0
- data/lib/libuv/ext/tasks/unix.rb +2 -0
- data/lib/libuv/ext/tasks/win.rb +2 -0
- data/lib/libuv/ext/types.rb +2 -1
- data/lib/libuv/file.rb +67 -50
- data/lib/libuv/filesystem.rb +63 -61
- data/lib/libuv/fs_event.rb +7 -4
- data/lib/libuv/handle.rb +30 -14
- data/lib/libuv/idle.rb +17 -10
- data/lib/libuv/mixins/accessors.rb +41 -0
- data/lib/libuv/mixins/assertions.rb +3 -1
- data/lib/libuv/mixins/fs_checks.rb +29 -6
- data/lib/libuv/mixins/listener.rb +4 -2
- data/lib/libuv/mixins/net.rb +4 -2
- data/lib/libuv/mixins/resource.rb +5 -3
- data/lib/libuv/mixins/stream.rb +128 -35
- data/lib/libuv/pipe.rb +54 -27
- data/lib/libuv/prepare.rb +19 -12
- data/lib/libuv/q.rb +109 -101
- data/lib/libuv/{loop.rb → reactor.rb} +163 -85
- data/lib/libuv/signal.rb +13 -5
- data/lib/libuv/tcp.rb +109 -63
- data/lib/libuv/timer.rb +44 -24
- data/lib/libuv/tty.rb +8 -3
- data/lib/libuv/udp.rb +49 -22
- data/lib/libuv/version.rb +3 -1
- data/lib/libuv/work.rb +14 -10
- data/libuv.gemspec +11 -9
- data/spec/async_spec.rb +13 -13
- data/spec/coroutines_spec.rb +20 -50
- data/spec/defer_spec.rb +182 -311
- data/spec/dns_spec.rb +51 -41
- data/spec/dsl_spec.rb +43 -0
- data/spec/filesystem_spec.rb +65 -87
- data/spec/idle_spec.rb +19 -33
- data/spec/pipe_spec.rb +25 -32
- data/spec/tcp_spec.rb +116 -53
- data/spec/timer_spec.rb +3 -3
- data/spec/udp_spec.rb +16 -17
- data/spec/zen_spec.rb +2 -3
- metadata +37 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 328790a2659803772fb2ca5891889bda349b47fd
|
4
|
+
data.tar.gz: 0b534aaeeb7fd1fbfd11c35090e8f048be6db411
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00f0aed38c13defc6a2e310a67e81f576fad3d90308d00575982794e4bad6d0f95204b20d5f66db130984e22223c616bc02f78b3ffbefcc2d623c8efec9b1516
|
7
|
+
data.tar.gz: da08a1d126e8d25dd0bb8fa8d0deb3a25d05a369725362d2aa5a4fbf5254aa2d5db7f6ec7f10c8b70ad2f24f2f6924018c59259276e83fa4d22eae58554a4599
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -4,60 +4,93 @@
|
|
4
4
|
|
5
5
|
[Libuv](https://github.com/libuv/libuv) is a cross platform asynchronous IO implementation that powers NodeJS. It supports sockets, both UDP and TCP, filesystem watch, TTY, Pipes and other asynchronous primitives like timer, check, prepare and idle.
|
6
6
|
|
7
|
-
The Libuv gem contains Libuv and a Ruby wrapper that implements [pipelined promises](http://en.wikipedia.org/wiki/Futures_and_promises#Promise_pipelining) for asynchronous flow control and [coroutines](http://en.wikipedia.org/wiki/Coroutine) for untangling evented code
|
7
|
+
The Libuv gem contains Libuv and a Ruby wrapper that implements [pipelined promises](http://en.wikipedia.org/wiki/Futures_and_promises#Promise_pipelining) for asynchronous flow control and [coroutines](http://en.wikipedia.org/wiki/Coroutine) / [futures](https://en.wikipedia.org/wiki/Futures_and_promises) for untangling evented code
|
8
8
|
|
9
9
|
## Usage
|
10
10
|
|
11
|
-
|
11
|
+
Libuv supports multiple reactors that can run on different threads.
|
12
|
+
|
13
|
+
For convenience the thread local or default reactor can be accessed via the `reactor` method
|
14
|
+
You can pass a block to be executed on the reactor and the reactor will run until there is nothing left to do.
|
12
15
|
|
13
16
|
```ruby
|
14
17
|
require 'libuv'
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
# loop = Libuv::Loop.new
|
19
|
-
|
20
|
-
loop.run do
|
21
|
-
timer = loop.timer do
|
19
|
+
reactor do |reactor|
|
20
|
+
reactor.timer {
|
22
21
|
puts "5 seconds passed"
|
23
|
-
|
24
|
-
end
|
25
|
-
timer.catch do |error|
|
26
|
-
puts "error with timer: #{error}"
|
27
|
-
end
|
28
|
-
timer.finally do
|
29
|
-
puts "timer handle was closed"
|
30
|
-
end
|
31
|
-
timer.start(5000)
|
22
|
+
}.start(5000)
|
32
23
|
end
|
24
|
+
|
25
|
+
puts "reactor stopped. No more IO to process"
|
33
26
|
```
|
34
27
|
|
35
|
-
|
28
|
+
Promises are used to simplify code flow.
|
36
29
|
|
37
30
|
```ruby
|
38
31
|
require 'libuv'
|
39
|
-
require 'libuv/coroutines'
|
40
32
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
33
|
+
reactor do |reactor|
|
34
|
+
reactor.tcp { |data, socket|
|
35
|
+
puts "received: #{data}"
|
36
|
+
socket.close
|
37
|
+
}
|
38
|
+
.connect('127.0.0.1', 3000) { |socket|
|
39
|
+
socket.start_read
|
40
|
+
.write("GET / HTTP/1.1\r\n\r\n")
|
41
|
+
}
|
42
|
+
.catch { |error|
|
43
|
+
puts "error: #{error}"
|
44
|
+
}
|
45
|
+
.finally {
|
46
|
+
puts "socket closed"
|
47
|
+
}
|
48
|
+
end
|
49
|
+
```
|
49
50
|
|
50
|
-
|
51
|
-
co timer
|
51
|
+
Continuations are used if callbacks are not defined
|
52
52
|
|
53
|
-
|
53
|
+
```ruby
|
54
|
+
require 'libuv'
|
55
|
+
|
56
|
+
reactor do |reactor|
|
57
|
+
begin
|
58
|
+
reactor.tcp { |data, socket|
|
59
|
+
puts "received: #{data}"
|
60
|
+
socket.close
|
61
|
+
}
|
62
|
+
.connect('127.0.0.1', 3000)
|
63
|
+
.start_read
|
64
|
+
.write("GET / HTTP/1.1\r\n\r\n")
|
54
65
|
rescue => error
|
55
|
-
puts "error
|
66
|
+
puts "error: #{error}"
|
56
67
|
end
|
57
68
|
end
|
58
69
|
```
|
59
70
|
|
60
|
-
|
71
|
+
Any promise can be converted into a continuation
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
require 'libuv'
|
75
|
+
|
76
|
+
reactor do |reactor|
|
77
|
+
# Perform work on the thread pool with promises
|
78
|
+
reactor.work {
|
79
|
+
10 * 2
|
80
|
+
}.then { |result|
|
81
|
+
puts "result using a promise #{result}"
|
82
|
+
}
|
83
|
+
|
84
|
+
# Use the coroutine helper to obtain the result without a callback
|
85
|
+
result = reactor.work {
|
86
|
+
10 * 3
|
87
|
+
}.value
|
88
|
+
puts "no additional callbacks here #{result}"
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
|
93
|
+
Check out the [yard documentation](http://rubydoc.info/gems/libuv/Libuv/Reactor)
|
61
94
|
|
62
95
|
|
63
96
|
## Installation
|
@@ -107,6 +140,6 @@ Windows users will additionally require:
|
|
107
140
|
* Filesystem Events
|
108
141
|
* Filesystem manipulation
|
109
142
|
* File manipulation
|
110
|
-
* Errors (with a catch-all fallback for anything unhandled on the event
|
143
|
+
* Errors (with a catch-all fallback for anything unhandled on the event reactor)
|
111
144
|
* Work queue (thread pool)
|
112
|
-
* Coroutines
|
145
|
+
* Coroutines / futures (makes use of Fibers)
|
data/lib/libuv.rb
CHANGED
@@ -1,21 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'forwardable'
|
4
|
+
require 'thread'
|
2
5
|
require 'ffi'
|
3
6
|
|
4
7
|
module Libuv
|
8
|
+
DefaultThread = Thread.current
|
9
|
+
|
5
10
|
require 'libuv/ext/ext' # The libuv ffi ext
|
6
11
|
require 'libuv/error' # List of errors (matching those in uv.h)
|
7
12
|
require 'libuv/q' # The promise library
|
8
13
|
|
9
|
-
# -- The classes required for a
|
14
|
+
# -- The classes required for a reactor instance --
|
10
15
|
require 'libuv/mixins/assertions' # Common code to check arguments
|
16
|
+
require 'libuv/mixins/accessors' # Helper methods for accessing reactor functions
|
11
17
|
require 'libuv/mixins/resource' # Common code to check for errors
|
12
18
|
require 'libuv/mixins/listener' # Common callback code
|
13
19
|
|
14
20
|
require 'libuv/handle' # Base class for most libuv functionality
|
15
|
-
require 'libuv/prepare' # Called at the end of a
|
16
|
-
require 'libuv/async' # Provide a threadsafe way to signal the event
|
21
|
+
require 'libuv/prepare' # Called at the end of a reactor cycle
|
22
|
+
require 'libuv/async' # Provide a threadsafe way to signal the event reactor
|
17
23
|
require 'libuv/timer' # High resolution timer
|
18
|
-
require 'libuv/
|
24
|
+
require 'libuv/reactor' # The libuv reactor or event reactor
|
25
|
+
require 'libuv/coroutines'
|
19
26
|
# --
|
20
27
|
|
21
28
|
autoload :FsChecks, 'libuv/mixins/fs_checks' # Common code to check file system results
|
@@ -25,7 +32,7 @@ module Libuv
|
|
25
32
|
autoload :Filesystem, 'libuv/filesystem' # Async directory manipulation
|
26
33
|
autoload :FSEvent, 'libuv/fs_event' # Notifies of changes to files and folders as they occur
|
27
34
|
autoload :Signal, 'libuv/signal' # Used to handle OS signals
|
28
|
-
autoload :Check, 'libuv/check' # Called before processing events on the
|
35
|
+
autoload :Check, 'libuv/check' # Called before processing events on the reactor
|
29
36
|
autoload :File, 'libuv/file' # Async file reading and writing
|
30
37
|
autoload :Idle, 'libuv/idle' # Called when there are no events to process
|
31
38
|
autoload :Work, 'libuv/work' # Provide work to be completed on another thread (thread pool)
|
@@ -52,4 +59,22 @@ module Libuv
|
|
52
59
|
return nil
|
53
60
|
end
|
54
61
|
end
|
62
|
+
|
63
|
+
# Include all the accessors at this level
|
64
|
+
extend Accessors
|
65
|
+
|
66
|
+
# Run the default reactor
|
67
|
+
at_exit do
|
68
|
+
reactor = Reactor.default
|
69
|
+
reactor.run if $!.nil? && reactor.run_count == 0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
class Object
|
75
|
+
private
|
76
|
+
|
77
|
+
def reactor(&blk)
|
78
|
+
Libuv.reactor &blk
|
79
|
+
end
|
55
80
|
end
|
data/lib/libuv/async.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Libuv
|
2
4
|
class Async < Handle
|
3
5
|
|
@@ -5,14 +7,14 @@ module Libuv
|
|
5
7
|
define_callback function: :on_async
|
6
8
|
|
7
9
|
|
8
|
-
# @param
|
9
|
-
def initialize(
|
10
|
-
@
|
10
|
+
# @param reactor [::Libuv::Reactor] reactor this async callback will be associated
|
11
|
+
def initialize(reactor, callback = nil, &blk)
|
12
|
+
@reactor = reactor
|
11
13
|
@callback = callback || blk
|
12
14
|
|
13
15
|
async_ptr = ::Libuv::Ext.allocate_handle_async
|
14
16
|
on_async = callback(:on_async, async_ptr.address)
|
15
|
-
error = check_result(::Libuv::Ext.async_init(
|
17
|
+
error = check_result(::Libuv::Ext.async_init(reactor.handle, async_ptr, on_async))
|
16
18
|
|
17
19
|
super(async_ptr, error)
|
18
20
|
end
|
@@ -22,13 +24,15 @@ module Libuv
|
|
22
24
|
return if @closed
|
23
25
|
error = check_result ::Libuv::Ext.async_send(handle)
|
24
26
|
reject(error) if error
|
27
|
+
self
|
25
28
|
end
|
26
29
|
|
27
30
|
# Used to update the callback that will be triggered when async is called
|
28
31
|
#
|
29
|
-
# @param callback [Proc] the callback to be called on
|
32
|
+
# @param callback [Proc] the callback to be called on reactor prepare
|
30
33
|
def progress(callback = nil, &blk)
|
31
34
|
@callback = callback || blk
|
35
|
+
self
|
32
36
|
end
|
33
37
|
|
34
38
|
|
@@ -36,11 +40,13 @@ module Libuv
|
|
36
40
|
|
37
41
|
|
38
42
|
def on_async(handle)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
::Fiber.new {
|
44
|
+
begin
|
45
|
+
@callback.call
|
46
|
+
rescue Exception => e
|
47
|
+
@reactor.log e, 'performing async callback'
|
48
|
+
end
|
49
|
+
}.resume
|
44
50
|
end
|
45
51
|
end
|
46
52
|
end
|
data/lib/libuv/check.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Libuv
|
2
4
|
class Check < Handle
|
3
5
|
|
@@ -5,14 +7,14 @@ module Libuv
|
|
5
7
|
define_callback function: :on_check
|
6
8
|
|
7
9
|
|
8
|
-
# @param
|
9
|
-
# @param callback [Proc] callback to be called on
|
10
|
-
def initialize(
|
11
|
-
@
|
10
|
+
# @param reactor [::Libuv::Reactor] reactor this check will be associated
|
11
|
+
# @param callback [Proc] callback to be called on reactor check
|
12
|
+
def initialize(reactor, callback = nil, &blk)
|
13
|
+
@reactor = reactor
|
12
14
|
@callback = callback || blk
|
13
15
|
|
14
16
|
check_ptr = ::Libuv::Ext.allocate_handle_check
|
15
|
-
error = check_result(::Libuv::Ext.check_init(
|
17
|
+
error = check_result(::Libuv::Ext.check_init(reactor.handle, check_ptr))
|
16
18
|
|
17
19
|
super(check_ptr, error)
|
18
20
|
end
|
@@ -22,6 +24,7 @@ module Libuv
|
|
22
24
|
return if @closed
|
23
25
|
error = check_result ::Libuv::Ext.check_start(handle, callback(:on_check))
|
24
26
|
reject(error) if error
|
27
|
+
self
|
25
28
|
end
|
26
29
|
|
27
30
|
# Disables the check handler.
|
@@ -29,13 +32,15 @@ module Libuv
|
|
29
32
|
return if @closed
|
30
33
|
error = check_result ::Libuv::Ext.check_stop(handle)
|
31
34
|
reject(error) if error
|
35
|
+
self
|
32
36
|
end
|
33
37
|
|
34
|
-
# Used to update the callback that will be triggered on
|
38
|
+
# Used to update the callback that will be triggered on reactor check
|
35
39
|
#
|
36
|
-
# @param callback [Proc] the callback to be called on
|
40
|
+
# @param callback [Proc] the callback to be called on reactor check
|
37
41
|
def progress(callback = nil, &blk)
|
38
42
|
@callback = callback || blk
|
43
|
+
self
|
39
44
|
end
|
40
45
|
|
41
46
|
|
@@ -43,11 +48,13 @@ module Libuv
|
|
43
48
|
|
44
49
|
|
45
50
|
def on_check(handle)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
+
::Fiber.new {
|
52
|
+
begin
|
53
|
+
@callback.call
|
54
|
+
rescue Exception => e
|
55
|
+
@reactor.log e, 'performing check callback'
|
56
|
+
end
|
57
|
+
}.resume
|
51
58
|
end
|
52
59
|
end
|
53
60
|
end
|
data/lib/libuv/coroutines.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fiber'
|
2
4
|
|
3
|
-
class
|
4
|
-
|
5
|
+
class CoroutineRejection < RuntimeError
|
6
|
+
attr_accessor :value
|
5
7
|
end
|
6
8
|
|
7
9
|
class Object
|
@@ -15,32 +17,57 @@ class Object
|
|
15
17
|
# @return [Object] Returns the result of a single promise or an array of results if provided multiple promises
|
16
18
|
# @raise [Exception] if the promise is rejected
|
17
19
|
def co(*yieldable, &block)
|
20
|
+
on_reactor = Libuv::Reactor.current
|
21
|
+
raise 'must be running on a reactor thread to use coroutines' unless on_reactor
|
22
|
+
|
18
23
|
f = Fiber.current
|
19
24
|
wasError = false
|
20
25
|
|
21
|
-
# Convert the input into a promise
|
26
|
+
# Convert the input into a promise on the current reactor
|
22
27
|
if yieldable.length == 1
|
23
28
|
promise = yieldable[0]
|
29
|
+
# Passed independently as this is often overwritten for performance
|
30
|
+
promise.progress(block) if block_given?
|
24
31
|
else
|
25
|
-
promise =
|
32
|
+
promise = on_reactor.all(*yieldable)
|
26
33
|
end
|
27
34
|
|
28
35
|
# Use the promise to resume the Fiber
|
29
36
|
promise.then(proc { |res|
|
30
|
-
|
37
|
+
if Libuv::Reactor.current == on_reactor
|
38
|
+
f.resume res
|
39
|
+
else
|
40
|
+
on_reactor.schedule { f.resume(res) }
|
41
|
+
end
|
31
42
|
}, proc { |err|
|
32
43
|
wasError = true
|
33
|
-
|
44
|
+
if Libuv::Reactor.current == on_reactor
|
45
|
+
f.resume err
|
46
|
+
else
|
47
|
+
on_reactor.schedule { f.resume(err) }
|
48
|
+
end
|
34
49
|
})
|
35
50
|
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
result = Fiber.yield
|
51
|
+
# We want to prevent the reactor from stopping while we are waiting on a response
|
52
|
+
on_reactor.ref
|
53
|
+
result = Fiber.yield # Assign the result from the resume
|
54
|
+
on_reactor.unref
|
41
55
|
|
42
56
|
# Either return the result or raise an error
|
43
|
-
|
57
|
+
if wasError
|
58
|
+
if result.is_a?(Exception)
|
59
|
+
raise result
|
60
|
+
else
|
61
|
+
e = case result
|
62
|
+
when String, Symbol
|
63
|
+
CoroutineRejection.new(result.to_s)
|
64
|
+
else
|
65
|
+
CoroutineRejection.new
|
66
|
+
end
|
67
|
+
e.value = result
|
68
|
+
raise e
|
69
|
+
end
|
70
|
+
end
|
44
71
|
result
|
45
72
|
end
|
46
73
|
end
|
data/lib/libuv/dns.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Libuv
|
2
4
|
class Dns < Q::DeferredPromise
|
3
5
|
include Resource, Listener, Net
|
@@ -28,11 +30,11 @@ module Libuv
|
|
28
30
|
end
|
29
31
|
|
30
32
|
|
31
|
-
# @param
|
33
|
+
# @param reactor [::Libuv::Reactor] reactor this work request will be associated
|
32
34
|
# @param domain [String] the domain name to resolve
|
33
35
|
# @param port [Integer, String] the port we wish to use
|
34
|
-
def initialize(
|
35
|
-
super(
|
36
|
+
def initialize(reactor, domain, port, hint = :IPv4, wait: true)
|
37
|
+
super(reactor, reactor.defer)
|
36
38
|
|
37
39
|
@domain = domain
|
38
40
|
@port = port
|
@@ -42,13 +44,15 @@ module Libuv
|
|
42
44
|
@error = nil # error in callback
|
43
45
|
|
44
46
|
@instance_id = @pointer.address
|
45
|
-
error = check_result ::Libuv::Ext.getaddrinfo(@
|
47
|
+
error = check_result ::Libuv::Ext.getaddrinfo(@reactor, @pointer, callback(:on_complete), domain, port.to_s, HINTS[hint])
|
46
48
|
|
47
49
|
if error
|
48
50
|
::Libuv::Ext.free(@pointer)
|
49
51
|
@complete = true
|
50
52
|
@defer.reject(error)
|
51
53
|
end
|
54
|
+
|
55
|
+
co(@defer.promise) if wait
|
52
56
|
end
|
53
57
|
|
54
58
|
# Indicates if the lookup has completed yet or not.
|
@@ -67,22 +71,25 @@ module Libuv
|
|
67
71
|
::Libuv::Ext.free(req)
|
68
72
|
|
69
73
|
e = check_result(status)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
begin
|
74
|
-
current = addrinfo
|
75
|
-
@results = []
|
76
|
-
while !current.null?
|
77
|
-
@results << get_ip_and_port(current[:addr])
|
78
|
-
current = current[:next]
|
79
|
-
end
|
80
|
-
@defer.resolve(@results)
|
81
|
-
rescue Exception => e
|
74
|
+
|
75
|
+
::Fiber.new {
|
76
|
+
if e
|
82
77
|
@defer.reject(e)
|
78
|
+
else
|
79
|
+
begin
|
80
|
+
current = addrinfo
|
81
|
+
@results = []
|
82
|
+
while !current.null?
|
83
|
+
@results << get_ip_and_port(current[:addr])
|
84
|
+
current = current[:next]
|
85
|
+
end
|
86
|
+
@defer.resolve(@results)
|
87
|
+
rescue Exception => e
|
88
|
+
@defer.reject(e)
|
89
|
+
end
|
90
|
+
::Libuv::Ext.freeaddrinfo(addrinfo)
|
83
91
|
end
|
84
|
-
|
85
|
-
end
|
92
|
+
}.resume
|
86
93
|
|
87
94
|
# Clean up references
|
88
95
|
cleanup_callbacks
|