cool.io 1.9.5 → 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/.github/workflows/test.yaml +1 -0
- data/.github/workflows/valgrind.yaml +0 -3
- data/Rakefile +1 -0
- data/ext/cool.io/buffer.c +32 -18
- data/ext/cool.io/ev_wrap.h +8 -0
- data/ext/cool.io/iowatcher.c +18 -1
- data/ext/cool.io/loop.c +6 -4
- data/ext/cool.io/stat_watcher.c +30 -18
- data/ext/cool.io/timer_watcher.c +1 -1
- data/ext/cool.io/watcher.h +0 -17
- data/ext/libev/ev.c +73 -11
- data/ext/libev/ev_vars.h +4 -0
- data/ext/libev/ev_win32_stat.c +851 -0
- data/ext/libev/ev_wrap.h +4 -0
- data/lib/cool.io/dns_resolver.rb +1 -0
- data/lib/cool.io/loop.rb +5 -1
- data/lib/cool.io/version.rb +1 -1
- data/spec/detach_race_condition_spec.rb +23 -11
- data/spec/dns_spec.rb +11 -0
- data/spec/fixtures/windows_stat_native.c +1376 -0
- data/spec/iobuffer_spec.rb +57 -1
- data/spec/loop_spec.rb +31 -0
- data/spec/stat_watcher_spec.rb +55 -0
- data/spec/tcp_server_spec.rb +6 -6
- data/spec/watcher_reattach_spec.rb +54 -0
- data/spec/windows_stat_native_spec.rb +212 -0
- data/spec/windows_stat_watcher_spec.rb +363 -0
- metadata +13 -2
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/.github/workflows/test.yaml
CHANGED
data/Rakefile
CHANGED
data/ext/cool.io/buffer.c
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
#include <unistd.h>
|
|
16
16
|
#endif
|
|
17
17
|
#include <errno.h>
|
|
18
|
+
#include <limits.h>
|
|
18
19
|
|
|
19
20
|
/* 1 GiB maximum buffer size */
|
|
20
21
|
#define MAX_BUFFER_SIZE 0x40000000
|
|
@@ -303,14 +304,17 @@ Coolio_Buffer_prepend(VALUE self, VALUE data)
|
|
|
303
304
|
|
|
304
305
|
/**
|
|
305
306
|
* call-seq:
|
|
306
|
-
* Coolio::Buffer#read
|
|
307
|
+
* Coolio::Buffer#read -> String
|
|
308
|
+
* Coolio::Buffer#read(length) -> String
|
|
307
309
|
*
|
|
308
|
-
* Read
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
310
|
+
* Read data from the buffer. Any data read from the buffer is cleared.
|
|
311
|
+
* With no argument, the entire contents of the buffer are returned. With
|
|
312
|
+
* length, at most length bytes are returned.
|
|
313
|
+
* At most LONG_MAX bytes are returned per call; on platforms where a String
|
|
314
|
+
* cannot hold the whole buffer the remainder is kept for later reads.
|
|
315
|
+
* length is converted with to_int, so nil raises TypeError. A length less
|
|
316
|
+
* than 1 raises ArgumentError, even when the buffer is empty.
|
|
317
|
+
* Otherwise, if the buffer is empty, an empty string is returned.
|
|
314
318
|
*/
|
|
315
319
|
static VALUE
|
|
316
320
|
Coolio_Buffer_read(int argc, VALUE * argv, VALUE self)
|
|
@@ -322,20 +326,24 @@ Coolio_Buffer_read(int argc, VALUE * argv, VALUE self)
|
|
|
322
326
|
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
323
327
|
|
|
324
328
|
if (rb_scan_args(argc, argv, "01", &length_obj) == 1) {
|
|
325
|
-
/*
|
|
326
|
-
*
|
|
327
|
-
|
|
328
|
-
|
|
329
|
+
/* Clamp before converting to C: long is only 32 bits on 64-bit Windows,
|
|
330
|
+
* and a request larger than the buffer never needs to fit in C at all.
|
|
331
|
+
* Keep the integer coercion and ArgumentError for non-positive lengths. */
|
|
332
|
+
VALUE requested = rb_to_int(length_obj);
|
|
333
|
+
if(rb_funcall(requested, rb_intern("<"), 1, INT2NUM(1)) == Qtrue)
|
|
329
334
|
rb_raise(rb_eArgError, "length must be greater than zero");
|
|
330
|
-
length =
|
|
331
|
-
if(length
|
|
332
|
-
length =
|
|
335
|
+
length = buf->size;
|
|
336
|
+
if(rb_funcall(requested, rb_intern("<"), 1, SIZET2NUM(length)) == Qtrue)
|
|
337
|
+
length = NUM2SIZET(requested);
|
|
333
338
|
} else
|
|
334
339
|
length = buf->size;
|
|
335
340
|
|
|
336
341
|
if(buf->size == 0)
|
|
337
342
|
return rb_str_new2("");
|
|
338
343
|
|
|
344
|
+
if(length > (size_t) LONG_MAX)
|
|
345
|
+
length = (size_t) LONG_MAX;
|
|
346
|
+
|
|
339
347
|
str = rb_str_new(0, (long) length);
|
|
340
348
|
buffer_read(buf, RSTRING_PTR(str), length);
|
|
341
349
|
|
|
@@ -384,6 +392,9 @@ Coolio_Buffer_to_str(VALUE self)
|
|
|
384
392
|
|
|
385
393
|
TypedData_Get_Struct(self, struct buffer, &Coolio_Buffer_type, buf);
|
|
386
394
|
|
|
395
|
+
if(buf->size > (size_t) LONG_MAX)
|
|
396
|
+
rb_raise(rb_eRangeError, "buffer is too large to convert to a String");
|
|
397
|
+
|
|
387
398
|
str = rb_str_new(0, (long) buf->size);
|
|
388
399
|
buffer_copy(buf, RSTRING_PTR(str), buf->size);
|
|
389
400
|
|
|
@@ -473,10 +484,13 @@ static void
|
|
|
473
484
|
buffer_clear(struct buffer * buf)
|
|
474
485
|
{
|
|
475
486
|
/* Move everything into the buffer pool */
|
|
476
|
-
if (
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
487
|
+
if (buf->head) {
|
|
488
|
+
if (!buf->pool_tail) {
|
|
489
|
+
buf->pool_head = buf->head;
|
|
490
|
+
} else {
|
|
491
|
+
buf->pool_tail->next = buf->head;
|
|
492
|
+
}
|
|
493
|
+
buf->pool_tail = buf->tail;
|
|
480
494
|
}
|
|
481
495
|
|
|
482
496
|
buf->head = buf->tail = 0;
|
data/ext/cool.io/ev_wrap.h
CHANGED
|
@@ -1,9 +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
|
|
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)
|
|
7
15
|
#endif
|
|
8
16
|
|
|
9
17
|
#include "../libev/ev.h"
|
data/ext/cool.io/iowatcher.c
CHANGED
|
@@ -111,7 +111,24 @@ static VALUE Coolio_IOWatcher_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
111
111
|
*/
|
|
112
112
|
static VALUE Coolio_IOWatcher_attach(VALUE self, VALUE loop)
|
|
113
113
|
{
|
|
114
|
-
|
|
114
|
+
struct Coolio_Watcher *watcher_data;
|
|
115
|
+
struct Coolio_Loop *loop_data;
|
|
116
|
+
|
|
117
|
+
if(!rb_obj_is_kind_of(loop, cCoolio_Loop))
|
|
118
|
+
rb_raise(rb_eArgError, "expected loop to be an instance of Coolio::Loop, not %s", RSTRING_PTR(rb_inspect(loop)));
|
|
119
|
+
|
|
120
|
+
watcher_data = Coolio_Watcher_ptr(self);
|
|
121
|
+
loop_data = Coolio_Loop_ptr(loop);
|
|
122
|
+
|
|
123
|
+
if(watcher_data->loop != Qnil)
|
|
124
|
+
rb_funcall(self, rb_intern("detach"), 0);
|
|
125
|
+
|
|
126
|
+
/* A new loop must resolve the Windows socket handle for this fd again. */
|
|
127
|
+
ev_io_set(&watcher_data->event_types.ev_io,
|
|
128
|
+
watcher_data->event_types.ev_io.fd, watcher_data->event_types.ev_io.events);
|
|
129
|
+
watcher_data->loop = loop;
|
|
130
|
+
ev_io_start(loop_data->ev_loop, &watcher_data->event_types.ev_io);
|
|
131
|
+
rb_call_super(1, &loop);
|
|
115
132
|
|
|
116
133
|
return self;
|
|
117
134
|
}
|
data/ext/cool.io/loop.c
CHANGED
|
@@ -81,10 +81,9 @@ static void Coolio_Loop_free(void *data)
|
|
|
81
81
|
{
|
|
82
82
|
struct Coolio_Loop *loop = data;
|
|
83
83
|
|
|
84
|
-
if(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
ev_loop_destroy(loop->ev_loop);
|
|
84
|
+
if(loop->ev_loop) {
|
|
85
|
+
ev_loop_destroy(loop->ev_loop);
|
|
86
|
+
}
|
|
88
87
|
|
|
89
88
|
xfree(loop->eventbuf);
|
|
90
89
|
xfree(loop);
|
|
@@ -100,6 +99,9 @@ static VALUE Coolio_Loop_ev_loop_new(VALUE self, VALUE flags)
|
|
|
100
99
|
rb_raise(rb_eRuntimeError, "loop already initialized");
|
|
101
100
|
|
|
102
101
|
loop_data->ev_loop = ev_loop_new(NUM2INT(flags));
|
|
102
|
+
if(!loop_data->ev_loop) {
|
|
103
|
+
rb_raise(rb_eRuntimeError, "unable to initialize the event loop (no usable backend)");
|
|
104
|
+
}
|
|
103
105
|
|
|
104
106
|
return Qnil;
|
|
105
107
|
}
|
data/ext/cool.io/stat_watcher.c
CHANGED
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
#include "ruby.h"
|
|
8
|
+
#ifdef _WIN32
|
|
9
|
+
#include "ruby/encoding.h"
|
|
10
|
+
#endif
|
|
8
11
|
#include "ev_wrap.h"
|
|
9
12
|
|
|
10
13
|
#include "cool.io.h"
|
|
@@ -74,8 +77,10 @@ void Init_coolio_stat_watcher()
|
|
|
74
77
|
* specified how often in seconds the path should be polled for changes.
|
|
75
78
|
* Setting interval to zero uses an "automatic" value (typically around 5
|
|
76
79
|
* seconds) which optimizes performance. Otherwise, values less than
|
|
77
|
-
* 0.1 are not particularly meaningful. Where available (
|
|
78
|
-
* high performance file monitoring interfaces
|
|
80
|
+
* 0.1 are not particularly meaningful. Where available (on Linux and Windows),
|
|
81
|
+
* high performance file monitoring interfaces are used. On Windows, polling
|
|
82
|
+
* remains necessary because notification timing is not guaranteed. An attached
|
|
83
|
+
* Windows watcher may also prevent renaming an ancestor directory until detached.
|
|
79
84
|
*/
|
|
80
85
|
static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self)
|
|
81
86
|
{
|
|
@@ -89,9 +94,14 @@ static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self)
|
|
|
89
94
|
interval = rb_convert_type(interval, T_FLOAT, "Float", "to_f");
|
|
90
95
|
|
|
91
96
|
path = rb_String(path);
|
|
92
|
-
path_str = StringValueCStr(path);
|
|
93
97
|
rb_iv_set(self, "@path", path);
|
|
94
98
|
|
|
99
|
+
#ifdef _WIN32
|
|
100
|
+
/* libev's wide Windows APIs and stat wrapper use UTF-8 paths. */
|
|
101
|
+
path = rb_str_export_to_enc(path, rb_utf8_encoding());
|
|
102
|
+
#endif
|
|
103
|
+
path_str = StringValueCStr(path);
|
|
104
|
+
|
|
95
105
|
watcher_data = Coolio_Watcher_ptr(self);
|
|
96
106
|
|
|
97
107
|
/* libev keeps the path pointer passed to ev_stat_init() for the lifetime of
|
|
@@ -136,7 +146,7 @@ static VALUE Coolio_StatWatcher_attach(VALUE self, VALUE loop)
|
|
|
136
146
|
watcher_data = Coolio_Watcher_ptr(self);
|
|
137
147
|
|
|
138
148
|
if(watcher_data->loop != Qnil)
|
|
139
|
-
|
|
149
|
+
rb_funcall(self, rb_intern("detach"), 0);
|
|
140
150
|
|
|
141
151
|
watcher_data->loop = loop;
|
|
142
152
|
|
|
@@ -248,20 +258,22 @@ static VALUE Coolio_StatInfo_build(ev_statdata *statdata_struct)
|
|
|
248
258
|
VALUE blksize = Qnil;
|
|
249
259
|
VALUE blocks = Qnil;
|
|
250
260
|
|
|
251
|
-
mtime = rb_funcall(cTime, at_method, 1,
|
|
252
|
-
ctime = rb_funcall(cTime, at_method, 1,
|
|
253
|
-
atime = rb_funcall(cTime, at_method, 1,
|
|
254
|
-
dev =
|
|
255
|
-
ino =
|
|
256
|
-
mode =
|
|
257
|
-
nlink =
|
|
258
|
-
uid =
|
|
259
|
-
gid =
|
|
260
|
-
rdev =
|
|
261
|
-
size =
|
|
262
|
-
#ifdef
|
|
263
|
-
blksize =
|
|
264
|
-
|
|
261
|
+
mtime = rb_funcall(cTime, at_method, 1, LL2NUM((long long)statdata_struct->st_mtime));
|
|
262
|
+
ctime = rb_funcall(cTime, at_method, 1, LL2NUM((long long)statdata_struct->st_ctime));
|
|
263
|
+
atime = rb_funcall(cTime, at_method, 1, LL2NUM((long long)statdata_struct->st_atime));
|
|
264
|
+
dev = LL2NUM((long long)statdata_struct->st_dev);
|
|
265
|
+
ino = ULL2NUM((unsigned long long)statdata_struct->st_ino);
|
|
266
|
+
mode = LL2NUM((long long)statdata_struct->st_mode);
|
|
267
|
+
nlink = LL2NUM((long long)statdata_struct->st_nlink);
|
|
268
|
+
uid = LL2NUM((long long)statdata_struct->st_uid);
|
|
269
|
+
gid = LL2NUM((long long)statdata_struct->st_gid);
|
|
270
|
+
rdev = LL2NUM((long long)statdata_struct->st_rdev);
|
|
271
|
+
size = LL2NUM((long long)statdata_struct->st_size);
|
|
272
|
+
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
|
273
|
+
blksize = LL2NUM((long long)statdata_struct->st_blksize);
|
|
274
|
+
#endif
|
|
275
|
+
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
|
276
|
+
blocks = LL2NUM((long long)statdata_struct->st_blocks);
|
|
265
277
|
#endif
|
|
266
278
|
|
|
267
279
|
return rb_struct_new(cCoolio_StatInfo,
|
data/ext/cool.io/timer_watcher.c
CHANGED
|
@@ -102,7 +102,7 @@ static VALUE Coolio_TimerWatcher_attach(VALUE self, VALUE loop)
|
|
|
102
102
|
watcher_data = Coolio_Watcher_ptr(self);
|
|
103
103
|
|
|
104
104
|
if(watcher_data->loop != Qnil)
|
|
105
|
-
|
|
105
|
+
rb_funcall(self, rb_intern("detach"), 0);
|
|
106
106
|
|
|
107
107
|
watcher_data->loop = loop;
|
|
108
108
|
|
data/ext/cool.io/watcher.h
CHANGED
|
@@ -7,23 +7,6 @@
|
|
|
7
7
|
#ifndef WATCHER_H
|
|
8
8
|
#define WATCHER_H
|
|
9
9
|
|
|
10
|
-
#define Watcher_Attach(watcher_type, detach_func, watcher, loop) \
|
|
11
|
-
struct Coolio_Watcher *watcher_data; \
|
|
12
|
-
struct Coolio_Loop *loop_data; \
|
|
13
|
-
\
|
|
14
|
-
if(!rb_obj_is_kind_of(loop, cCoolio_Loop)) \
|
|
15
|
-
rb_raise(rb_eArgError, "expected loop to be an instance of Coolio::Loop, not %s", RSTRING_PTR(rb_inspect(loop))); \
|
|
16
|
-
\
|
|
17
|
-
watcher_data = Coolio_Watcher_ptr(watcher); \
|
|
18
|
-
loop_data = Coolio_Loop_ptr(loop); \
|
|
19
|
-
\
|
|
20
|
-
if(watcher_data->loop != Qnil) \
|
|
21
|
-
detach_func(watcher); \
|
|
22
|
-
\
|
|
23
|
-
watcher_data->loop = loop; \
|
|
24
|
-
ev_##watcher_type##_start(loop_data->ev_loop, &watcher_data->event_types.ev_##watcher_type); \
|
|
25
|
-
rb_call_super(1, &loop)
|
|
26
|
-
|
|
27
10
|
#define Watcher_Detach(watcher_type, watcher) \
|
|
28
11
|
struct Coolio_Watcher *watcher_data; \
|
|
29
12
|
\
|
data/ext/libev/ev.c
CHANGED
|
@@ -219,6 +219,11 @@
|
|
|
219
219
|
# endif
|
|
220
220
|
# include <winsock2.h>
|
|
221
221
|
# include <windows.h>
|
|
222
|
+
# include <process.h>
|
|
223
|
+
# ifndef EV_WIN32_STAT_CODEPAGE
|
|
224
|
+
/* Interpret narrow paths using the active Windows code page unless overridden. */
|
|
225
|
+
# define EV_WIN32_STAT_CODEPAGE CP_ACP
|
|
226
|
+
# endif
|
|
222
227
|
# ifndef EV_SELECT_IS_WINSOCKET
|
|
223
228
|
# define EV_SELECT_IS_WINSOCKET 1
|
|
224
229
|
# endif
|
|
@@ -1855,6 +1860,10 @@ typedef struct
|
|
|
1855
1860
|
|
|
1856
1861
|
#endif
|
|
1857
1862
|
|
|
1863
|
+
#if defined(_WIN32) && EV_STAT_ENABLE && EV_ASYNC_ENABLE
|
|
1864
|
+
static void win32_fs_destroy (EV_P);
|
|
1865
|
+
#endif
|
|
1866
|
+
|
|
1858
1867
|
#if EV_FEATURE_API
|
|
1859
1868
|
# define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A)
|
|
1860
1869
|
# define EV_ACQUIRE_CB if (expect_false (acquire_cb)) acquire_cb (EV_A)
|
|
@@ -2406,8 +2415,8 @@ static ANSIG signals [EV_NSIG - 1];
|
|
|
2406
2415
|
#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
|
|
2407
2416
|
|
|
2408
2417
|
noinline ecb_cold
|
|
2409
|
-
static
|
|
2410
|
-
|
|
2418
|
+
static int
|
|
2419
|
+
evpipe_init_try (EV_P)
|
|
2411
2420
|
{
|
|
2412
2421
|
if (!ev_is_active (&pipe_w))
|
|
2413
2422
|
{
|
|
@@ -2422,8 +2431,8 @@ evpipe_init (EV_P)
|
|
|
2422
2431
|
if (fds [1] < 0)
|
|
2423
2432
|
# endif
|
|
2424
2433
|
{
|
|
2425
|
-
|
|
2426
|
-
|
|
2434
|
+
if (pipe (fds))
|
|
2435
|
+
return 0;
|
|
2427
2436
|
|
|
2428
2437
|
fd_intern (fds [0]);
|
|
2429
2438
|
}
|
|
@@ -2449,6 +2458,16 @@ evpipe_init (EV_P)
|
|
|
2449
2458
|
ev_io_start (EV_A_ &pipe_w);
|
|
2450
2459
|
ev_unref (EV_A); /* watcher should not keep loop alive */
|
|
2451
2460
|
}
|
|
2461
|
+
|
|
2462
|
+
return 1;
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
noinline ecb_cold
|
|
2466
|
+
static void
|
|
2467
|
+
evpipe_init (EV_P)
|
|
2468
|
+
{
|
|
2469
|
+
while (!evpipe_init_try (EV_A))
|
|
2470
|
+
ev_syserr ("(libev) error creating signal/async pipe");
|
|
2452
2471
|
}
|
|
2453
2472
|
|
|
2454
2473
|
inline_speed void
|
|
@@ -2914,6 +2933,10 @@ loop_init (EV_P_ unsigned int flags) EV_THROW
|
|
|
2914
2933
|
pipe_write_wanted = 0;
|
|
2915
2934
|
evpipe [0] = -1;
|
|
2916
2935
|
evpipe [1] = -1;
|
|
2936
|
+
#if defined(_WIN32) && EV_STAT_ENABLE && EV_ASYNC_ENABLE
|
|
2937
|
+
win32_fs = 0;
|
|
2938
|
+
win32_fs_disabled = (flags & EVFLAG_NOINOTIFY) != 0;
|
|
2939
|
+
#endif
|
|
2917
2940
|
#if EV_USE_INOTIFY
|
|
2918
2941
|
fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2;
|
|
2919
2942
|
#endif
|
|
@@ -2982,6 +3005,10 @@ ev_loop_destroy (EV_P)
|
|
|
2982
3005
|
}
|
|
2983
3006
|
#endif
|
|
2984
3007
|
|
|
3008
|
+
#if defined(_WIN32) && EV_STAT_ENABLE && EV_ASYNC_ENABLE
|
|
3009
|
+
win32_fs_destroy (EV_A);
|
|
3010
|
+
#endif
|
|
3011
|
+
|
|
2985
3012
|
if (ev_is_active (&pipe_w))
|
|
2986
3013
|
{
|
|
2987
3014
|
/*ev_ref (EV_A);*/
|
|
@@ -4330,17 +4357,16 @@ ev_child_stop (EV_P_ ev_child *w) EV_THROW
|
|
|
4330
4357
|
|
|
4331
4358
|
#if EV_STAT_ENABLE
|
|
4332
4359
|
|
|
4333
|
-
# ifdef _WIN32
|
|
4334
|
-
# undef lstat
|
|
4335
|
-
# define lstat(a,b) _stati64 (a,b)
|
|
4336
|
-
# endif
|
|
4337
|
-
|
|
4338
4360
|
#define DEF_STAT_INTERVAL 5.0074891
|
|
4339
4361
|
#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */
|
|
4340
4362
|
#define MIN_STAT_INTERVAL 0.1074891
|
|
4341
4363
|
|
|
4342
4364
|
noinline static void stat_timer_cb (EV_P_ ev_timer *w_, int revents);
|
|
4343
4365
|
|
|
4366
|
+
#if defined(_WIN32) && EV_ASYNC_ENABLE
|
|
4367
|
+
# include "ev_win32_stat.c"
|
|
4368
|
+
#endif
|
|
4369
|
+
|
|
4344
4370
|
#if EV_USE_INOTIFY
|
|
4345
4371
|
|
|
4346
4372
|
/* the * 2 is to allow for alignment padding, which for some reason is >> 8 */
|
|
@@ -4581,7 +4607,23 @@ infy_fork (EV_P)
|
|
|
4581
4607
|
#endif
|
|
4582
4608
|
|
|
4583
4609
|
#ifdef _WIN32
|
|
4584
|
-
|
|
4610
|
+
static int
|
|
4611
|
+
win32_stat (const char *path, ev_statdata *attr)
|
|
4612
|
+
{
|
|
4613
|
+
int result;
|
|
4614
|
+
int length = MultiByteToWideChar (EV_WIN32_STAT_CODEPAGE, 0, path, -1, 0, 0);
|
|
4615
|
+
wchar_t *wide;
|
|
4616
|
+
if (!length)
|
|
4617
|
+
{ errno = EINVAL; return -1; }
|
|
4618
|
+
wide = (wchar_t *)malloc (length * sizeof (wchar_t));
|
|
4619
|
+
if (!wide)
|
|
4620
|
+
{ errno = ENOMEM; return -1; }
|
|
4621
|
+
MultiByteToWideChar (EV_WIN32_STAT_CODEPAGE, 0, path, -1, wide, length);
|
|
4622
|
+
result = _wstati64 (wide, attr);
|
|
4623
|
+
free (wide);
|
|
4624
|
+
return result;
|
|
4625
|
+
}
|
|
4626
|
+
# define EV_LSTAT(p,b) win32_stat (p, b)
|
|
4585
4627
|
#else
|
|
4586
4628
|
# define EV_LSTAT(p,b) lstat (p, b)
|
|
4587
4629
|
#endif
|
|
@@ -4589,7 +4631,7 @@ infy_fork (EV_P)
|
|
|
4589
4631
|
void
|
|
4590
4632
|
ev_stat_stat (EV_P_ ev_stat *w) EV_THROW
|
|
4591
4633
|
{
|
|
4592
|
-
if (
|
|
4634
|
+
if (EV_LSTAT (w->path, &w->attr) < 0)
|
|
4593
4635
|
w->attr.st_nlink = 0;
|
|
4594
4636
|
else if (!w->attr.st_nlink)
|
|
4595
4637
|
w->attr.st_nlink = 1;
|
|
@@ -4601,6 +4643,11 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
|
|
|
4601
4643
|
{
|
|
4602
4644
|
ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer));
|
|
4603
4645
|
|
|
4646
|
+
#if defined(_WIN32) && EV_ASYNC_ENABLE
|
|
4647
|
+
if (revents & EV_TIMER)
|
|
4648
|
+
win32_fs_add (EV_A_ w, 1); /* retry missing parents or failed directory handles */
|
|
4649
|
+
#endif
|
|
4650
|
+
|
|
4604
4651
|
ev_statdata prev = w->attr;
|
|
4605
4652
|
ev_stat_stat (EV_A_ w);
|
|
4606
4653
|
|
|
@@ -4623,6 +4670,12 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
|
|
|
4623
4670
|
/* to ensure that prev is always different to attr */
|
|
4624
4671
|
w->prev = prev;
|
|
4625
4672
|
|
|
4673
|
+
#if defined(_WIN32) && EV_ASYNC_ENABLE
|
|
4674
|
+
if (!prev.st_nlink || !w->attr.st_nlink
|
|
4675
|
+
|| (prev.st_mode & S_IFMT) != (w->attr.st_mode & S_IFMT))
|
|
4676
|
+
win32_fs_add (EV_A_ w, 0); /* register directory children after creation */
|
|
4677
|
+
#endif
|
|
4678
|
+
|
|
4626
4679
|
#if EV_USE_INOTIFY
|
|
4627
4680
|
if (fs_fd >= 0)
|
|
4628
4681
|
{
|
|
@@ -4664,6 +4717,11 @@ ev_stat_start (EV_P_ ev_stat *w) EV_THROW
|
|
|
4664
4717
|
|
|
4665
4718
|
ev_start (EV_A_ (W)w, 1);
|
|
4666
4719
|
|
|
4720
|
+
#if defined(_WIN32) && EV_ASYNC_ENABLE
|
|
4721
|
+
win32_fs_add (EV_A_ w, 0);
|
|
4722
|
+
stat_timer_cb (EV_A_ &w->timer, 0); /* close the stat/registration race */
|
|
4723
|
+
#endif
|
|
4724
|
+
|
|
4667
4725
|
EV_FREQUENT_CHECK;
|
|
4668
4726
|
}
|
|
4669
4727
|
|
|
@@ -4676,6 +4734,10 @@ ev_stat_stop (EV_P_ ev_stat *w) EV_THROW
|
|
|
4676
4734
|
|
|
4677
4735
|
EV_FREQUENT_CHECK;
|
|
4678
4736
|
|
|
4737
|
+
#if defined(_WIN32) && EV_ASYNC_ENABLE
|
|
4738
|
+
win32_fs_del (EV_A_ w);
|
|
4739
|
+
#endif
|
|
4740
|
+
|
|
4679
4741
|
#if EV_USE_INOTIFY
|
|
4680
4742
|
infy_del (EV_A_ w);
|
|
4681
4743
|
#endif
|
data/ext/libev/ev_vars.h
CHANGED
|
@@ -181,6 +181,10 @@ VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
|
|
|
181
181
|
#endif
|
|
182
182
|
|
|
183
183
|
VARx(EV_ATOMIC_T, sig_pending)
|
|
184
|
+
#if defined(_WIN32) && EV_STAT_ENABLE && EV_ASYNC_ENABLE
|
|
185
|
+
VARx(struct ev_win32_fs *, win32_fs)
|
|
186
|
+
VARx(int, win32_fs_disabled)
|
|
187
|
+
#endif
|
|
184
188
|
#if EV_USE_SIGNALFD || EV_GENWRAP
|
|
185
189
|
VARx(int, sigfd)
|
|
186
190
|
VARx(ev_io, sigfd_w)
|