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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9494578f6a02a987a84805bca37919a7c0e63c4c585a7bdf8c68e18e38d21e8d
4
- data.tar.gz: 0cae209afee54a8f6f59014afb71ee2357dabdc350cfc60dfe2a6212062dbf1e
3
+ metadata.gz: 84ec70f3ced722b0919a7e3348a6670e9d474343f8b831d9e942222a1edd0314
4
+ data.tar.gz: b60d4526c1c799119c43db2ae0e0f3debb85cba85086a6c65868477398a88a66
5
5
  SHA512:
6
- metadata.gz: ccb23719b38180b44cd6485901a35a15710daf77f4079a7fbdbc1d77fcfe86b75787d82c8cd8f455f5199a7f390125d6d62320eeff2785b2193c6fe5612c7653
7
- data.tar.gz: 2ab5356bc8ab69fb93c6f3c6532ada9c67b63c774e7a952f20526b1bf3660fde681a3b480130deaf436212b4b0d77b51859fefcb9d4f0a6dc983b0a46de70f2c
6
+ metadata.gz: 924f47393f2ae881e1afb914fa16bb67089840e8ef1c3599502919c5fa53263c06e0f6303d263ae376d8bff33da00ad9577b6549e3fc5128ead104a4f383e9d2
7
+ data.tar.gz: 8929ec98ce4161507309610d762c5f22f7fe4b756c361902fb0e37afa69ee2d8adc788383866ec7c9d270b80f27a99e902c2ef5128804e3b9e86c2b46c6e0535
@@ -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"
@@ -1,5 +1,5 @@
1
1
  module Coolio
2
- VERSION = "1.10.0"
2
+ VERSION = "1.10.1"
3
3
 
4
4
  def self.version
5
5
  VERSION
@@ -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.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cool.io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri