nio4r 2.4.0 → 2.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 93a1a241691b4115c57d823095030d46f36640184d6dc479ec0c46ac3e730d43
4
- data.tar.gz: c0795ea1c7e4c3d9a0f6347ce69f3d937f0410618e80c217cc5c54c90bf44ddb
3
+ metadata.gz: f6a583408aa1022eb39933974b8d93536a4deedc497e4bcbf15afe70cce85aae
4
+ data.tar.gz: 39bf6f00cc0b1386354cbdbafe8616d3be0221aa1a519ba1888a55fb17145049
5
5
  SHA512:
6
- metadata.gz: 289370e25ed8f9692699a493d7cae6dccb5a24db65af58053c094a529eac7e3a65b9581f7576e46661e02a4ef017defdd1ca3805a7e1e1db38025f4c62513e6e
7
- data.tar.gz: 854804c274c63ef8590164ef733d2a538e004d744e13090b1c60ef0b070617e3a49d3c528d50da940c02855446e057e33674f97c121f73c0295e3ea0d96dcd54
6
+ metadata.gz: fa5347e538b5a8c83a3c92cb83375af906bc2af1c38b76f69c1d33495bee264bda59ce72e9c28c6246a94c6ff7d8db1c9879ab95c2ff343eff1ac04e5b6afe22
7
+ data.tar.gz: afaa2cd96dc17e0f8738922b44d92ece039d5b66240a5e5f67e695d8b6c20744ec2ab49b1c4a0c0d0d8e5bd22617ade144294f7767576f5d033ce73de4934061
@@ -1,8 +1,12 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  dist: xenial
4
+ env: OS="xenial 16.04"
4
5
  bundler_args: --without development
5
6
 
7
+ after_script:
8
+ - ruby -ropenssl -e "puts ENV['OS'], RUBY_DESCRIPTION, OpenSSL::OPENSSL_LIBRARY_VERSION"
9
+
6
10
  matrix:
7
11
  fast_finish: true
8
12
  include:
@@ -12,8 +16,19 @@ matrix:
12
16
  - rvm: 2.6
13
17
  env: NIO4R_PURE=true
14
18
  - rvm: 2.6
19
+ - rvm: 2.3
20
+ dist: trusty
21
+ env: OS="trusty 14.04"
22
+ - rvm: 2.6.3
23
+ dist: bionic
24
+ env: OS="bionic 18.04"
15
25
  - rvm: 2.6
16
26
  os: osx
27
+ env: OS="osx"
28
+ - rvm: 2.4.6
29
+ os: osx
30
+ osx_image: xcode10.2
31
+ env: OS="osx xcode 10.2"
17
32
  - rvm: truffleruby
18
33
  - rvm: truffleruby
19
34
  env: NIO4R_PURE=true
data/CHANGES.md CHANGED
@@ -1,3 +1,24 @@
1
+ ## 2.4.0 (2019-07-07)
2
+
3
+ * [#211](https://github.com/socketry/nio4r/pull/211)
4
+ Enable KQUEUE on macOS 10.14+.
5
+ ([@ioquatix])
6
+
7
+ * Bump minimum supported Ruby to 2.3.
8
+ ([@ioquatix])
9
+
10
+ * Assorted fixes for TruffleRuby & JRuby.
11
+ ([@eregon], [@olleolleolle])
12
+
13
+ * Update libev to v4.25.
14
+ ([@ioquatix])
15
+
16
+ * Bind to ephemeral (port 0) for more reliable specs.
17
+ ([@ioquatix])
18
+
19
+ * Improve handling of SSL sockets and related specs.
20
+ ([@MSP-Greg])
21
+
1
22
  ## 2.3.1 (2018-05-03)
2
23
 
3
24
  * [#188](https://github.com/socketry/nio4r/pull/188)
@@ -219,3 +240,5 @@
219
240
  [@HoneyryderChuck]: https://github.com/HoneyryderChuck
220
241
  [@tompng]: https://github.com/tompng
221
242
  [@ioquatix]: https://github.com/ioquatix
243
+ [@eregon]: https://github.com/eregon
244
+ [@olleolleolle]: https://github.com/olleolleolle
data/README.md CHANGED
@@ -27,10 +27,12 @@ writing.
27
27
  * [ActionCable]: Rails 5 WebSocket protocol, uses nio4r for a WebSocket server
28
28
  * [Celluloid::IO]: Actor-based concurrency framework, uses nio4r for async I/O
29
29
  * [Socketry Async]: Asynchronous I/O framework for Ruby
30
+ * [Puma]: Ruby/Rack web server built for concurrency
30
31
 
31
32
  [ActionCable]: https://rubygems.org/gems/actioncable
32
33
  [Celluloid::IO]: https://github.com/celluloid/celluloid-io
33
34
  [Socketry Async]: https://github.com/socketry/async
35
+ [Puma]: https://github.com/puma/puma
34
36
 
35
37
  ## Goals
36
38
 
@@ -45,7 +47,8 @@ writing.
45
47
  * Ruby 2.4
46
48
  * Ruby 2.5
47
49
  * Ruby 2.6
48
- * JRuby 9000
50
+ * [JRuby](https://github.com/jruby/jruby)
51
+ * [TruffleRuby](https://github.com/oracle/truffleruby)
49
52
 
50
53
  ## Supported backends
51
54
 
@@ -96,11 +99,33 @@ to maintain a large codebase.
96
99
 
97
100
  ## License
98
101
 
99
- Copyright (c) 2011-2018 Tony Arcieri. Distributed under the MIT License.
100
- See [LICENSE.txt] for further details.
102
+ Released under the MIT license.
101
103
 
102
- Includes libev 4.24. Copyright (c) 2007-2016 Marc Alexander Lehmann.
103
- Distributed under the BSD license. See [ext/libev/LICENSE] for details.
104
+ Copyright, 2019, by Tony Arcieri.
105
+ Copyright, 2019, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
106
+
107
+ Permission is hereby granted, free of charge, to any person obtaining a copy
108
+ of this software and associated documentation files (the "Software"), to deal
109
+ in the Software without restriction, including without limitation the rights
110
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
111
+ copies of the Software, and to permit persons to whom the Software is
112
+ furnished to do so, subject to the following conditions:
113
+
114
+ The above copyright notice and this permission notice shall be included in
115
+ all copies or substantial portions of the Software.
116
+
117
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
118
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
119
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
120
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
121
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
122
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
123
+ THE SOFTWARE.
124
+
125
+ ### libev
126
+
127
+ Released under the BSD license. See [ext/libev/LICENSE] for details.
128
+
129
+ Copyright, 2007-2019, by Marc Alexander Lehmann.
104
130
 
105
- [LICENSE.txt]: https://github.com/socketry/nio4r/blob/master/LICENSE.txt
106
131
  [ext/libev/LICENSE]: https://github.com/socketry/nio4r/blob/master/ext/libev/LICENSE
@@ -1,8 +1,27 @@
1
1
  Revision history for libev, a high-performance and full-featured event loop.
2
2
 
3
+ 4.27 Thu Jun 27 22:43:44 CEST 2019
4
+ - linux aio backend almost complete rewritten to work around its
5
+ limitations.
6
+ - epoll backend now mandatory for linux aio backend.
7
+ - fail assertions more aggressively on invalid fd's detected
8
+ in the event loop, do not just silently fd_kill in case of
9
+ user error.
10
+ - ev_io_start/ev_io_stop now verify the watcher fd using
11
+ a syscall when EV_VERIFY is 2 or higher.
12
+
13
+ 4.26 (EV only)
14
+ - update to libecb 0x00010006.
15
+ - new experimental linux aio backend (linux 4.18+).
16
+ - removed redundant 0-ptr check in ev_once.
17
+ - updated/extended ev_set_allocator documentation.
18
+ - replaced EMPTY2 macro by array_needsize_noinit.
19
+ - minor code cleanups.
20
+ - epoll backend now uses epoll_create1 also after fork.
21
+
3
22
  4.25 Fri Dec 21 07:49:20 CET 2018
4
23
  - INCOMPATIBLE CHANGE: EV_THROW was renamed to EV_NOEXCEPT
5
- (EV_THROW sitll provided) and now uses noexcept on C++11 or newer.
24
+ (EV_THROW still provided) and now uses noexcept on C++11 or newer.
6
25
  - move the darwin select workaround highe rin ev.c, as newer versions of
7
26
  darwin managed to break their broken select even more.
8
27
  - ANDROID => __ANDROID__ (reported by enh@google.com).
@@ -18,7 +18,8 @@ ABOUT
18
18
  - extensive and detailed, readable documentation (not doxygen garbage).
19
19
  - fully supports fork, can detect fork in various ways and automatically
20
20
  re-arms kernel mechanisms that do not support fork.
21
- - highly optimised select, poll, epoll, kqueue and event ports backends.
21
+ - highly optimised select, poll, linux epoll, linux aio, bsd kqueue
22
+ and solaris event ports backends.
22
23
  - filesystem object (path) watching (with optional linux inotify support).
23
24
  - wallclock-based times (using absolute time, cron-like).
24
25
  - relative timers/timeouts (handle time jumps).
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libev event processing core, watcher management
3
3
  *
4
- * Copyright (c) 2007-2018 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007-2019 Marc Alexander Lehmann <libev@schmorp.de>
5
5
  * All rights reserved.
6
6
  *
7
7
  * Redistribution and use in source and binary forms, with or without modifica-
@@ -126,6 +126,15 @@
126
126
  # define EV_USE_EPOLL 0
127
127
  # endif
128
128
 
129
+ # if HAVE_LINUX_AIO_ABI_H
130
+ # ifndef EV_USE_LINUXAIO
131
+ # define EV_USE_LINUXAIO EV_FEATURE_BACKENDS
132
+ # endif
133
+ # else
134
+ # undef EV_USE_LINUXAIO
135
+ # define EV_USE_LINUXAIO 0
136
+ # endif
137
+
129
138
  # if HAVE_KQUEUE && HAVE_SYS_EVENT_H
130
139
  # ifndef EV_USE_KQUEUE
131
140
  # define EV_USE_KQUEUE EV_FEATURE_BACKENDS
@@ -326,6 +335,14 @@
326
335
  # define EV_USE_PORT 0
327
336
  #endif
328
337
 
338
+ #ifndef EV_USE_LINUXAIO
339
+ # if __linux /* libev currently assumes linux/aio_abi.h is always available on linux */
340
+ # define EV_USE_LINUXAIO 1
341
+ # else
342
+ # define EV_USE_LINUXAIO 0
343
+ # endif
344
+ #endif
345
+
329
346
  #ifndef EV_USE_INOTIFY
330
347
  # if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
331
348
  # define EV_USE_INOTIFY EV_FEATURE_OS
@@ -430,6 +447,14 @@
430
447
  # endif
431
448
  #endif
432
449
 
450
+ #if EV_USE_LINUXAIO
451
+ # include <sys/syscall.h>
452
+ # if !SYS_io_getevents || !EV_USE_EPOLL /* ev_linxaio uses ev_poll.c:ev_epoll_create */
453
+ # undef EV_USE_LINUXAIO
454
+ # define EV_USE_LINUXAIO 0
455
+ # endif
456
+ #endif
457
+
433
458
  #if EV_USE_INOTIFY
434
459
  # include <sys/statfs.h>
435
460
  # include <sys/inotify.h>
@@ -545,7 +570,7 @@ struct signalfd_siginfo
545
570
  #define ECB_H
546
571
 
547
572
  /* 16 bits major, 16 bits minor */
548
- #define ECB_VERSION 0x00010005
573
+ #define ECB_VERSION 0x00010006
549
574
 
550
575
  #ifdef _WIN32
551
576
  typedef signed char int8_t;
@@ -669,6 +694,7 @@ struct signalfd_siginfo
669
694
 
670
695
  #ifndef ECB_MEMORY_FENCE
671
696
  #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
697
+ #define ECB_MEMORY_FENCE_RELAXED __asm__ __volatile__ ("" : : : "memory")
672
698
  #if __i386 || __i386__
673
699
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
674
700
  #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
@@ -728,12 +754,14 @@ struct signalfd_siginfo
728
754
  #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST)
729
755
  #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)
730
756
  #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)
757
+ #define ECB_MEMORY_FENCE_RELAXED __atomic_thread_fence (__ATOMIC_RELAXED)
731
758
 
732
759
  #elif ECB_CLANG_EXTENSION(c_atomic)
733
760
  /* see comment below (stdatomic.h) about the C11 memory model. */
734
761
  #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
735
762
  #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)
736
763
  #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)
764
+ #define ECB_MEMORY_FENCE_RELAXED __c11_atomic_thread_fence (__ATOMIC_RELAXED)
737
765
 
738
766
  #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
739
767
  #define ECB_MEMORY_FENCE __sync_synchronize ()
@@ -753,9 +781,10 @@ struct signalfd_siginfo
753
781
  #define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
754
782
  #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
755
783
  #include <mbarrier.h>
756
- #define ECB_MEMORY_FENCE __machine_rw_barrier ()
757
- #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier ()
758
- #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier ()
784
+ #define ECB_MEMORY_FENCE __machine_rw_barrier ()
785
+ #define ECB_MEMORY_FENCE_ACQUIRE __machine_acq_barrier ()
786
+ #define ECB_MEMORY_FENCE_RELEASE __machine_rel_barrier ()
787
+ #define ECB_MEMORY_FENCE_RELAXED __compiler_barrier ()
759
788
  #elif __xlC__
760
789
  #define ECB_MEMORY_FENCE __sync ()
761
790
  #endif
@@ -766,15 +795,9 @@ struct signalfd_siginfo
766
795
  /* we assume that these memory fences work on all variables/all memory accesses, */
767
796
  /* not just C11 atomics and atomic accesses */
768
797
  #include <stdatomic.h>
769
- /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */
770
- /* any fence other than seq_cst, which isn't very efficient for us. */
771
- /* Why that is, we don't know - either the C11 memory model is quite useless */
772
- /* for most usages, or gcc and clang have a bug */
773
- /* I *currently* lean towards the latter, and inefficiently implement */
774
- /* all three of ecb's fences as a seq_cst fence */
775
- /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */
776
- /* for all __atomic_thread_fence's except seq_cst */
777
798
  #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst)
799
+ #define ECB_MEMORY_FENCE_ACQUIRE atomic_thread_fence (memory_order_acquire)
800
+ #define ECB_MEMORY_FENCE_RELEASE atomic_thread_fence (memory_order_release)
778
801
  #endif
779
802
  #endif
780
803
 
@@ -804,6 +827,10 @@ struct signalfd_siginfo
804
827
  #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
805
828
  #endif
806
829
 
830
+ #if !defined ECB_MEMORY_FENCE_RELAXED && defined ECB_MEMORY_FENCE
831
+ #define ECB_MEMORY_FENCE_RELAXED ECB_MEMORY_FENCE /* very heavy-handed */
832
+ #endif
833
+
807
834
  /*****************************************************************************/
808
835
 
809
836
  #if ECB_CPP
@@ -1554,8 +1581,7 @@ ecb_binary32_to_binary16 (uint32_t x)
1554
1581
  # define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
1555
1582
  #endif
1556
1583
 
1557
- #define EMPTY /* required for microsofts broken pseudo-c compiler */
1558
- #define EMPTY2(a,b) /* used to suppress some warnings */
1584
+ #define EMPTY /* required for microsofts broken pseudo-c compiler */
1559
1585
 
1560
1586
  typedef ev_watcher *W;
1561
1587
  typedef ev_watcher_list *WL;
@@ -1590,6 +1616,10 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
1590
1616
 
1591
1617
  /*****************************************************************************/
1592
1618
 
1619
+ #if EV_USE_LINUXAIO
1620
+ # include <linux/aio_abi.h> /* probably only needed for aio_context_t */
1621
+ #endif
1622
+
1593
1623
  /* define a suitable floor function (only used by periodics atm) */
1594
1624
 
1595
1625
  #if EV_USE_FLOOR
@@ -1781,7 +1811,7 @@ typedef struct
1781
1811
  WL head;
1782
1812
  unsigned char events; /* the events watched for */
1783
1813
  unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */
1784
- unsigned char emask; /* the epoll backend stores the actual kernel mask in here */
1814
+ unsigned char emask; /* some backends store the actual kernel mask in here */
1785
1815
  unsigned char unused;
1786
1816
  #if EV_USE_EPOLL
1787
1817
  unsigned int egen; /* generation counter to counter epoll bugs */
@@ -1972,8 +2002,10 @@ array_realloc (int elem, void *base, int *cur, int cnt)
1972
2002
  return ev_realloc (base, elem * *cur);
1973
2003
  }
1974
2004
 
1975
- #define array_init_zero(base,count) \
1976
- memset ((void *)(base), 0, sizeof (*(base)) * (count))
2005
+ #define array_needsize_noinit(base,offset,count)
2006
+
2007
+ #define array_needsize_zerofill(base,offset,count) \
2008
+ memset ((void *)(base + offset), 0, sizeof (*(base)) * (count))
1977
2009
 
1978
2010
  #define array_needsize(type,base,cur,cnt,init) \
1979
2011
  if (expect_false ((cnt) > (cur))) \
@@ -1981,7 +2013,7 @@ array_realloc (int elem, void *base, int *cur, int cnt)
1981
2013
  ecb_unused int ocur_ = (cur); \
1982
2014
  (base) = (type *)array_realloc \
1983
2015
  (sizeof (type), (base), &(cur), (cnt)); \
1984
- init ((base) + (ocur_), (cur) - ocur_); \
2016
+ init ((base), ocur_, ((cur) - ocur_)); \
1985
2017
  }
1986
2018
 
1987
2019
  #if 0
@@ -2018,7 +2050,7 @@ ev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT
2018
2050
  else
2019
2051
  {
2020
2052
  w_->pending = ++pendingcnt [pri];
2021
- array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, EMPTY2);
2053
+ array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, array_needsize_noinit);
2022
2054
  pendings [pri][w_->pending - 1].w = w_;
2023
2055
  pendings [pri][w_->pending - 1].events = revents;
2024
2056
  }
@@ -2029,7 +2061,7 @@ ev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT
2029
2061
  inline_speed void
2030
2062
  feed_reverse (EV_P_ W w)
2031
2063
  {
2032
- array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, EMPTY2);
2064
+ array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, array_needsize_noinit);
2033
2065
  rfeeds [rfeedcnt++] = w;
2034
2066
  }
2035
2067
 
@@ -2126,7 +2158,7 @@ fd_reify (EV_P)
2126
2158
  unsigned char o_events = anfd->events;
2127
2159
  unsigned char o_reify = anfd->reify;
2128
2160
 
2129
- anfd->reify = 0;
2161
+ anfd->reify = 0;
2130
2162
 
2131
2163
  /*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */
2132
2164
  {
@@ -2157,7 +2189,7 @@ fd_change (EV_P_ int fd, int flags)
2157
2189
  if (expect_true (!reify))
2158
2190
  {
2159
2191
  ++fdchangecnt;
2160
- array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2);
2192
+ array_needsize (int, fdchanges, fdchangemax, fdchangecnt, array_needsize_noinit);
2161
2193
  fdchanges [fdchangecnt - 1] = fd;
2162
2194
  }
2163
2195
  }
@@ -2717,6 +2749,9 @@ childcb (EV_P_ ev_signal *sw, int revents)
2717
2749
  #if EV_USE_EPOLL
2718
2750
  # include "ev_epoll.c"
2719
2751
  #endif
2752
+ #if EV_USE_LINUXAIO
2753
+ # include "ev_linuxaio.c"
2754
+ #endif
2720
2755
  #if EV_USE_POLL
2721
2756
  # include "ev_poll.c"
2722
2757
  #endif
@@ -2754,11 +2789,12 @@ ev_supported_backends (void) EV_NOEXCEPT
2754
2789
  {
2755
2790
  unsigned int flags = 0;
2756
2791
 
2757
- if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
2758
- if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE;
2759
- if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
2760
- if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
2761
- if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;
2792
+ if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
2793
+ if (EV_USE_KQUEUE ) flags |= EVBACKEND_KQUEUE;
2794
+ if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
2795
+ if (EV_USE_LINUXAIO) flags |= EVBACKEND_LINUXAIO;
2796
+ if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
2797
+ if (EV_USE_SELECT ) flags |= EVBACKEND_SELECT;
2762
2798
 
2763
2799
  return flags;
2764
2800
  }
@@ -2784,6 +2820,11 @@ ev_recommended_backends (void) EV_NOEXCEPT
2784
2820
  flags &= ~EVBACKEND_POLL; /* poll return value is unusable (http://forums.freebsd.org/archive/index.php/t-10270.html) */
2785
2821
  #endif
2786
2822
 
2823
+ /* TODO: linuxaio is very experimental */
2824
+ #if !EV_RECOMMEND_LINUXAIO
2825
+ flags &= ~EVBACKEND_LINUXAIO;
2826
+ #endif
2827
+
2787
2828
  return flags;
2788
2829
  }
2789
2830
 
@@ -2928,22 +2969,25 @@ loop_init (EV_P_ unsigned int flags) EV_NOEXCEPT
2928
2969
  flags |= ev_recommended_backends ();
2929
2970
 
2930
2971
  #if EV_USE_IOCP
2931
- if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
2972
+ if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
2932
2973
  #endif
2933
2974
  #if EV_USE_PORT
2934
- if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
2975
+ if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
2935
2976
  #endif
2936
2977
  #if EV_USE_KQUEUE
2937
- if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags);
2978
+ if (!backend && (flags & EVBACKEND_KQUEUE )) backend = kqueue_init (EV_A_ flags);
2979
+ #endif
2980
+ #if EV_USE_LINUXAIO
2981
+ if (!backend && (flags & EVBACKEND_LINUXAIO)) backend = linuxaio_init (EV_A_ flags);
2938
2982
  #endif
2939
2983
  #if EV_USE_EPOLL
2940
- if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
2984
+ if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
2941
2985
  #endif
2942
2986
  #if EV_USE_POLL
2943
- if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
2987
+ if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
2944
2988
  #endif
2945
2989
  #if EV_USE_SELECT
2946
- if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);
2990
+ if (!backend && (flags & EVBACKEND_SELECT )) backend = select_init (EV_A_ flags);
2947
2991
  #endif
2948
2992
 
2949
2993
  ev_prepare_init (&pending_w, pendingcb);
@@ -3008,22 +3052,25 @@ ev_loop_destroy (EV_P)
3008
3052
  close (backend_fd);
3009
3053
 
3010
3054
  #if EV_USE_IOCP
3011
- if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
3055
+ if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
3012
3056
  #endif
3013
3057
  #if EV_USE_PORT
3014
- if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
3058
+ if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
3015
3059
  #endif
3016
3060
  #if EV_USE_KQUEUE
3017
- if (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A);
3061
+ if (backend == EVBACKEND_KQUEUE ) kqueue_destroy (EV_A);
3062
+ #endif
3063
+ #if EV_USE_LINUXAIO
3064
+ if (backend == EVBACKEND_LINUXAIO) linuxaio_destroy (EV_A);
3018
3065
  #endif
3019
3066
  #if EV_USE_EPOLL
3020
- if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
3067
+ if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
3021
3068
  #endif
3022
3069
  #if EV_USE_POLL
3023
- if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
3070
+ if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
3024
3071
  #endif
3025
3072
  #if EV_USE_SELECT
3026
- if (backend == EVBACKEND_SELECT) select_destroy (EV_A);
3073
+ if (backend == EVBACKEND_SELECT ) select_destroy (EV_A);
3027
3074
  #endif
3028
3075
 
3029
3076
  for (i = NUMPRI; i--; )
@@ -3075,13 +3122,16 @@ inline_size void
3075
3122
  loop_fork (EV_P)
3076
3123
  {
3077
3124
  #if EV_USE_PORT
3078
- if (backend == EVBACKEND_PORT ) port_fork (EV_A);
3125
+ if (backend == EVBACKEND_PORT ) port_fork (EV_A);
3079
3126
  #endif
3080
3127
  #if EV_USE_KQUEUE
3081
- if (backend == EVBACKEND_KQUEUE) kqueue_fork (EV_A);
3128
+ if (backend == EVBACKEND_KQUEUE ) kqueue_fork (EV_A);
3129
+ #endif
3130
+ #if EV_USE_LINUXAIO
3131
+ if (backend == EVBACKEND_LINUXAIO) linuxaio_fork (EV_A);
3082
3132
  #endif
3083
3133
  #if EV_USE_EPOLL
3084
- if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
3134
+ if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
3085
3135
  #endif
3086
3136
  #if EV_USE_INOTIFY
3087
3137
  infy_fork (EV_A);
@@ -3598,7 +3648,7 @@ int
3598
3648
  ev_run (EV_P_ int flags)
3599
3649
  {
3600
3650
  /* ########## NIO4R PATCHERY HO! ########## */
3601
- struct ev_poll_args poll_args;
3651
+ struct ev_poll_args poll_args;
3602
3652
  /* ######################################## */
3603
3653
 
3604
3654
  #if EV_FEATURE_API
@@ -3951,10 +4001,13 @@ ev_io_start (EV_P_ ev_io *w) EV_NOEXCEPT
3951
4001
  assert (("libev: ev_io_start called with negative fd", fd >= 0));
3952
4002
  assert (("libev: ev_io_start called with illegal event mask", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE))));
3953
4003
 
4004
+ #if EV_VERIFY >= 2
4005
+ assert (("libev: ev_io_start called on watcher with invalid fd", fd_valid (fd)));
4006
+ #endif
3954
4007
  EV_FREQUENT_CHECK;
3955
4008
 
3956
4009
  ev_start (EV_A_ (W)w, 1);
3957
- array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
4010
+ array_needsize (ANFD, anfds, anfdmax, fd + 1, array_needsize_zerofill);
3958
4011
  wlist_add (&anfds[fd].head, (WL)w);
3959
4012
 
3960
4013
  /* common bug, apparently */
@@ -3976,6 +4029,9 @@ ev_io_stop (EV_P_ ev_io *w) EV_NOEXCEPT
3976
4029
 
3977
4030
  assert (("libev: ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
3978
4031
 
4032
+ #if EV_VERIFY >= 2
4033
+ assert (("libev: ev_io_stop called on watcher with invalid fd", fd_valid (w->fd)));
4034
+ #endif
3979
4035
  EV_FREQUENT_CHECK;
3980
4036
 
3981
4037
  wlist_del (&anfds[w->fd].head, (WL)w);
@@ -4001,7 +4057,7 @@ ev_timer_start (EV_P_ ev_timer *w) EV_NOEXCEPT
4001
4057
 
4002
4058
  ++timercnt;
4003
4059
  ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);
4004
- array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2);
4060
+ array_needsize (ANHE, timers, timermax, ev_active (w) + 1, array_needsize_noinit);
4005
4061
  ANHE_w (timers [ev_active (w)]) = (WT)w;
4006
4062
  ANHE_at_cache (timers [ev_active (w)]);
4007
4063
  upheap (timers, ev_active (w));
@@ -4098,7 +4154,7 @@ ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT
4098
4154
 
4099
4155
  ++periodiccnt;
4100
4156
  ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1);
4101
- array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, EMPTY2);
4157
+ array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, array_needsize_noinit);
4102
4158
  ANHE_w (periodics [ev_active (w)]) = (WT)w;
4103
4159
  ANHE_at_cache (periodics [ev_active (w)]);
4104
4160
  upheap (periodics, ev_active (w));
@@ -4693,7 +4749,7 @@ ev_idle_start (EV_P_ ev_idle *w) EV_NOEXCEPT
4693
4749
  ++idleall;
4694
4750
  ev_start (EV_A_ (W)w, active);
4695
4751
 
4696
- array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, EMPTY2);
4752
+ array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, array_needsize_noinit);
4697
4753
  idles [ABSPRI (w)][active - 1] = w;
4698
4754
  }
4699
4755
 
@@ -4733,7 +4789,7 @@ ev_prepare_start (EV_P_ ev_prepare *w) EV_NOEXCEPT
4733
4789
  EV_FREQUENT_CHECK;
4734
4790
 
4735
4791
  ev_start (EV_A_ (W)w, ++preparecnt);
4736
- array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
4792
+ array_needsize (ev_prepare *, prepares, preparemax, preparecnt, array_needsize_noinit);
4737
4793
  prepares [preparecnt - 1] = w;
4738
4794
 
4739
4795
  EV_FREQUENT_CHECK;
@@ -4771,7 +4827,7 @@ ev_check_start (EV_P_ ev_check *w) EV_NOEXCEPT
4771
4827
  EV_FREQUENT_CHECK;
4772
4828
 
4773
4829
  ev_start (EV_A_ (W)w, ++checkcnt);
4774
- array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);
4830
+ array_needsize (ev_check *, checks, checkmax, checkcnt, array_needsize_noinit);
4775
4831
  checks [checkcnt - 1] = w;
4776
4832
 
4777
4833
  EV_FREQUENT_CHECK;
@@ -4919,7 +4975,7 @@ ev_fork_start (EV_P_ ev_fork *w) EV_NOEXCEPT
4919
4975
  EV_FREQUENT_CHECK;
4920
4976
 
4921
4977
  ev_start (EV_A_ (W)w, ++forkcnt);
4922
- array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);
4978
+ array_needsize (ev_fork *, forks, forkmax, forkcnt, array_needsize_noinit);
4923
4979
  forks [forkcnt - 1] = w;
4924
4980
 
4925
4981
  EV_FREQUENT_CHECK;
@@ -4957,7 +5013,7 @@ ev_cleanup_start (EV_P_ ev_cleanup *w) EV_NOEXCEPT
4957
5013
  EV_FREQUENT_CHECK;
4958
5014
 
4959
5015
  ev_start (EV_A_ (W)w, ++cleanupcnt);
4960
- array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, EMPTY2);
5016
+ array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, array_needsize_noinit);
4961
5017
  cleanups [cleanupcnt - 1] = w;
4962
5018
 
4963
5019
  /* cleanup watchers should never keep a refcount on the loop */
@@ -5002,7 +5058,7 @@ ev_async_start (EV_P_ ev_async *w) EV_NOEXCEPT
5002
5058
  EV_FREQUENT_CHECK;
5003
5059
 
5004
5060
  ev_start (EV_A_ (W)w, ++asynccnt);
5005
- array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2);
5061
+ array_needsize (ev_async *, asyncs, asyncmax, asynccnt, array_needsize_noinit);
5006
5062
  asyncs [asynccnt - 1] = w;
5007
5063
 
5008
5064
  EV_FREQUENT_CHECK;
@@ -5081,12 +5137,6 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
5081
5137
  {
5082
5138
  struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
5083
5139
 
5084
- if (expect_false (!once))
5085
- {
5086
- cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMER, arg);
5087
- return;
5088
- }
5089
-
5090
5140
  once->cb = cb;
5091
5141
  once->arg = arg;
5092
5142