nio4r 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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