cool.io 1.10.0 → 1.10.1
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/ext/cool.io/ev_wrap.h +7 -0
- data/lib/cool.io/version.rb +1 -1
- data/spec/fixtures/windows_stat_native.c +71 -0
- data/spec/windows_stat_native_spec.rb +19 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 84ec70f3ced722b0919a7e3348a6670e9d474343f8b831d9e942222a1edd0314
|
|
4
|
+
data.tar.gz: b60d4526c1c799119c43db2ae0e0f3debb85cba85086a6c65868477398a88a66
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 924f47393f2ae881e1afb914fa16bb67089840e8ef1c3599502919c5fa53263c06e0f6303d263ae376d8bff33da00ad9577b6549e3fc5128ead104a4f383e9d2
|
|
7
|
+
data.tar.gz: 8929ec98ce4161507309610d762c5f22f7fe4b756c361902fb0e37afa69ee2d8adc788383866ec7c9d270b80f27a99e902c2ef5128804e3b9e86c2b46c6e0535
|
data/ext/cool.io/ev_wrap.h
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
#define EV_STANDALONE /* keeps ev from requiring config.h */
|
|
2
2
|
|
|
3
3
|
#ifdef _WIN32
|
|
4
|
+
#include "ruby.h"
|
|
4
5
|
#define EV_SELECT_IS_WINSOCKET 1 /* configure libev for windows select */
|
|
5
6
|
#define EV_USE_MONOTONIC 0
|
|
6
7
|
#define EV_USE_REALTIME 0
|
|
7
8
|
#define EV_WIN32_STAT_CODEPAGE CP_UTF8 /* Ruby paths are UTF-8. */
|
|
9
|
+
/* Close the evpipe sockets with closesocket() through Ruby. The CRT close()
|
|
10
|
+
* only calls CloseHandle(), which leaves Winsock state behind. A socket later
|
|
11
|
+
* imported from a WSAPROTOCOL_INFO with the same handle value inherits it, and
|
|
12
|
+
* listen() fails with WSAEISCONN. */
|
|
13
|
+
#define EV_WIN32_HANDLE_TO_FD(handle) rb_w32_wrap_io_handle((HANDLE)(handle), 0)
|
|
14
|
+
#define EV_WIN32_CLOSE_FD(fd) rb_w32_close(fd)
|
|
8
15
|
#endif
|
|
9
16
|
|
|
10
17
|
#include "../libev/ev.h"
|
data/lib/cool.io/version.rb
CHANGED
|
@@ -1284,6 +1284,76 @@ alias_recovery (VALUE self, VALUE path)
|
|
|
1284
1284
|
retried ? Qtrue : Qfalse, cached ? Qtrue : Qfalse);
|
|
1285
1285
|
}
|
|
1286
1286
|
|
|
1287
|
+
static VALUE
|
|
1288
|
+
imported_listen_failures (VALUE self, VALUE tries)
|
|
1289
|
+
{
|
|
1290
|
+
enum { limit = 64 };
|
|
1291
|
+
WSADATA data;
|
|
1292
|
+
WSAPROTOCOL_INFOW info;
|
|
1293
|
+
struct sockaddr_in addr;
|
|
1294
|
+
SOCKET sockets[limit * 2], base, imported;
|
|
1295
|
+
const char *failure = 0;
|
|
1296
|
+
int i, error = 0, opened = 0, failures = 0, count = NUM2INT (tries);
|
|
1297
|
+
if (count < 0 || count > limit)
|
|
1298
|
+
{
|
|
1299
|
+
rb_raise (rb_eArgError, "tries must be between 0 and %d", limit);
|
|
1300
|
+
}
|
|
1301
|
+
if (WSAStartup (MAKEWORD (2, 2), &data))
|
|
1302
|
+
{
|
|
1303
|
+
rb_raise (rb_eRuntimeError, "WSAStartup failed");
|
|
1304
|
+
}
|
|
1305
|
+
memset (&addr, 0, sizeof (addr));
|
|
1306
|
+
addr.sin_family = AF_INET;
|
|
1307
|
+
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
|
1308
|
+
for (i = 0; i < count; ++i)
|
|
1309
|
+
{
|
|
1310
|
+
base = WSASocketW (AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
|
|
1311
|
+
if (base == INVALID_SOCKET)
|
|
1312
|
+
{
|
|
1313
|
+
failure = "WSASocketW failed";
|
|
1314
|
+
error = WSAGetLastError ();
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1317
|
+
sockets[opened++] = base;
|
|
1318
|
+
if (bind (base, (struct sockaddr *)&addr, sizeof (addr))
|
|
1319
|
+
|| WSADuplicateSocketW (base, GetCurrentProcessId (), &info))
|
|
1320
|
+
{
|
|
1321
|
+
failure = "could not prepare a socket to import";
|
|
1322
|
+
error = WSAGetLastError ();
|
|
1323
|
+
break;
|
|
1324
|
+
}
|
|
1325
|
+
imported = WSASocketW (FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
|
|
1326
|
+
&info, 0, WSA_FLAG_OVERLAPPED);
|
|
1327
|
+
if (imported == INVALID_SOCKET)
|
|
1328
|
+
{
|
|
1329
|
+
failure = "WSASocketW could not import the socket";
|
|
1330
|
+
error = WSAGetLastError ();
|
|
1331
|
+
break;
|
|
1332
|
+
}
|
|
1333
|
+
sockets[opened++] = imported;
|
|
1334
|
+
if (listen (imported, 1) == SOCKET_ERROR)
|
|
1335
|
+
{
|
|
1336
|
+
error = WSAGetLastError ();
|
|
1337
|
+
if (error != WSAEISCONN)
|
|
1338
|
+
{
|
|
1339
|
+
failure = "listen failed";
|
|
1340
|
+
break;
|
|
1341
|
+
}
|
|
1342
|
+
++failures;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
while (opened)
|
|
1346
|
+
{
|
|
1347
|
+
closesocket (sockets[--opened]);
|
|
1348
|
+
}
|
|
1349
|
+
WSACleanup ();
|
|
1350
|
+
if (failure)
|
|
1351
|
+
{
|
|
1352
|
+
rb_raise (rb_eRuntimeError, "%s: %d", failure, error);
|
|
1353
|
+
}
|
|
1354
|
+
return INT2NUM (failures);
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1287
1357
|
RUBY_FUNC_EXPORTED void
|
|
1288
1358
|
Init_coolio_stat_native (void)
|
|
1289
1359
|
{
|
|
@@ -1302,4 +1372,5 @@ Init_coolio_stat_native (void)
|
|
|
1302
1372
|
rb_define_singleton_method (module, "children_cwd", children_cwd, 3);
|
|
1303
1373
|
rb_define_singleton_method (module, "replaced_dir", replaced_dir, 2);
|
|
1304
1374
|
rb_define_singleton_method (module, "alias_recovery", alias_recovery, 1);
|
|
1375
|
+
rb_define_singleton_method (module, "imported_listen_failures", imported_listen_failures, 1);
|
|
1305
1376
|
}
|
|
@@ -177,6 +177,25 @@ describe 'Windows stat notification internals', :if => RUBY_PLATFORM =~ /mingw|m
|
|
|
177
177
|
expect(result).to eq([true, true, true, true])
|
|
178
178
|
end
|
|
179
179
|
|
|
180
|
+
it 'closes the notification pipe of a destroyed loop so that imported sockets can listen' do
|
|
181
|
+
lib = File.expand_path('../lib', __dir__)
|
|
182
|
+
result = native_result(<<~'RUBY', lib, @build)
|
|
183
|
+
$LOAD_PATH.unshift(ARGV[0])
|
|
184
|
+
require 'cool.io'
|
|
185
|
+
path = File.join(ARGV[1], 'evpipe.txt')
|
|
186
|
+
File.write(path, 'a')
|
|
187
|
+
20.times do
|
|
188
|
+
reactor = Coolio::Loop.new
|
|
189
|
+
watcher = Coolio::StatWatcher.new(path, 60)
|
|
190
|
+
watcher.attach(reactor)
|
|
191
|
+
watcher.detach
|
|
192
|
+
end
|
|
193
|
+
3.times { GC.start }
|
|
194
|
+
$stdout.write(Marshal.dump(CoolioStatNativeSpec.imported_listen_failures(30)))
|
|
195
|
+
RUBY
|
|
196
|
+
expect(result).to eq(0)
|
|
197
|
+
end
|
|
198
|
+
|
|
180
199
|
it 'uses effective notification flags and respects EVFLAG_NOENV' do
|
|
181
200
|
path = File.join(@build, 'flags.txt')
|
|
182
201
|
# EVFLAG_NOINOTIFY = 0x00100000; EVFLAG_NOENV = 0x01000000.
|