ebb 0.1.0 → 0.2.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.
- data/README +4 -7
- data/benchmark/application.rb +12 -4
- data/benchmark/server_test.rb +10 -11
- data/bin/ebb_rails +0 -0
- data/libev/ev.c +235 -128
- data/libev/ev.h +84 -27
- data/libev/ev_epoll.c +30 -22
- data/libev/ev_kqueue.c +30 -22
- data/libev/ev_poll.c +30 -22
- data/libev/ev_port.c +30 -22
- data/libev/ev_select.c +34 -26
- data/libev/ev_vars.h +49 -0
- data/libev/ev_win32.c +31 -23
- data/libev/ev_wrap.h +12 -0
- data/ruby_lib/ebb.rb +94 -67
- data/ruby_lib/ebb/runner.rb +4 -5
- data/ruby_lib/ebb/runner/rails.rb +1 -4
- data/ruby_lib/rack/adapter/rails.rb +5 -0
- data/src/ebb.c +261 -387
- data/src/ebb.h +19 -29
- data/src/ebb_ruby.c +113 -108
- data/src/extconf.rb +0 -1
- data/src/parser.c +1755 -724
- data/src/parser.h +13 -10
- data/test/basic_test.rb +18 -1
- data/test/env_test.rb +6 -5
- data/test/helper.rb +53 -1
- metadata +3 -4
- data/benchmark/bench_results.rb +0 -58
data/README
CHANGED
@@ -53,7 +53,7 @@ hacking at the moment! :)
|
|
53
53
|
|
54
54
|
## Speed
|
55
55
|
|
56
|
-
Because Ebb
|
56
|
+
Because Ebb handles most of the processing in C, it is able to do work
|
57
57
|
often times more efficiently than other Ruby language web servers.
|
58
58
|
|
59
59
|

|
@@ -70,17 +70,14 @@ Contributions (patches, criticism, advice) are very welcome!
|
|
70
70
|
Please send all to to
|
71
71
|
[the mailing list](http://groups.google.com/group/ebbebb).
|
72
72
|
|
73
|
-
The source code
|
74
|
-
|
75
|
-
by executing
|
73
|
+
The source code is hosted [github](http://github.com/ry/ebb/tree/master). It
|
74
|
+
can be retrieved by executing
|
76
75
|
|
77
76
|
git clone git://github.com/ry/ebb.git
|
78
77
|
|
79
78
|
Here are some features that I would like to add:
|
80
79
|
* HTTP 1.1 Expect/Continue (RFC 2616, sections 8.2.3 and 10.1.1)
|
81
|
-
* A parser for multipart/form-data
|
82
|
-
* Optimize and clean up upload handling
|
83
|
-
* Option to listen on unix sockets instead of TCP
|
80
|
+
* A parser for multipart/form-data (only for optimization - this functionality is currently handled at the framework level)
|
84
81
|
* Python binding
|
85
82
|
|
86
83
|
## (The MIT) License
|
data/benchmark/application.rb
CHANGED
@@ -20,8 +20,13 @@ class SimpleApp
|
|
20
20
|
@count = 0
|
21
21
|
end
|
22
22
|
|
23
|
+
def deferred?(env)
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
23
27
|
def call(env)
|
24
|
-
|
28
|
+
path = env['PATH_INFO'] || env['REQUEST_URI']
|
29
|
+
commands = path.split('/')
|
25
30
|
|
26
31
|
@count += 1
|
27
32
|
if commands.include?('periodical_activity') and @count % 10 != 1
|
@@ -52,12 +57,12 @@ class SimpleApp
|
|
52
57
|
while chunk = env['rack.input'].read(512)
|
53
58
|
input_body << chunk
|
54
59
|
end
|
55
|
-
if env['
|
60
|
+
if env['CONTENT_LENGTH'].to_i == input_body.length
|
56
61
|
body = "Content-Length matches input length"
|
57
62
|
status = 200
|
58
63
|
else
|
59
64
|
body = "Content-Length doesn't matches input length!
|
60
|
-
content_length = #{env['
|
65
|
+
content_length = #{env['CONTENT_LENGTH'].to_i}
|
61
66
|
input_body.length = #{input_body.length}"
|
62
67
|
status = 500
|
63
68
|
end
|
@@ -67,12 +72,15 @@ class SimpleApp
|
|
67
72
|
body = "Undefined url"
|
68
73
|
end
|
69
74
|
|
70
|
-
|
75
|
+
body += "\r\n"
|
76
|
+
headers = {'Content-Type' => 'text/plain', 'Content-Length' => body.length.to_s }
|
77
|
+
[status, headers, body]
|
71
78
|
end
|
72
79
|
end
|
73
80
|
|
74
81
|
|
75
82
|
if $0 == __FILE__
|
76
83
|
require DIR + '/../ruby_lib/ebb'
|
84
|
+
#server = Ebb::start_server(SimpleApp.new, :unix_socket => '/tmp/ebb.sock')
|
77
85
|
server = Ebb::start_server(SimpleApp.new, :port => 4001)
|
78
86
|
end
|
data/benchmark/server_test.rb
CHANGED
@@ -115,10 +115,8 @@ class ServerTest
|
|
115
115
|
case name
|
116
116
|
when 'emongrel'
|
117
117
|
@pid = fork { start_emongrel }
|
118
|
-
when '
|
119
|
-
@pid = fork {
|
120
|
-
when 'ebb_sequential'
|
121
|
-
@pid = fork { start_ebb_sequential }
|
118
|
+
when 'ebb'
|
119
|
+
@pid = fork { start_ebb }
|
122
120
|
when 'mongrel'
|
123
121
|
@pid = fork { start_mongrel }
|
124
122
|
when 'thin'
|
@@ -139,15 +137,11 @@ class ServerTest
|
|
139
137
|
Rack::Handler::Mongrel.run(app, :Host => '0.0.0.0', :Port => @port.to_i)
|
140
138
|
end
|
141
139
|
|
142
|
-
def
|
140
|
+
def start_ebb
|
143
141
|
require File.dirname(__FILE__) + '/../ruby_lib/ebb'
|
144
|
-
server = Ebb::start_server(app, :port => @port
|
142
|
+
server = Ebb::start_server(app, :port => @port)
|
145
143
|
end
|
146
144
|
|
147
|
-
def start_ebb_sequential
|
148
|
-
require File.dirname(__FILE__) + '/../ruby_lib/ebb'
|
149
|
-
server = Ebb::start_server(app, :port => @port, :threaded_processing => false)
|
150
|
-
end
|
151
145
|
|
152
146
|
def start_mongrel
|
153
147
|
require 'mongrel'
|
@@ -173,6 +167,9 @@ class ServerTest
|
|
173
167
|
|
174
168
|
return nil unless r =~ /Requests per second:\s*(\d+\.\d\d)/
|
175
169
|
rps = $1.to_f
|
170
|
+
if r =~ /Time taken for tests:\s*(\d+\.\d+) seconds/
|
171
|
+
time_taken = $1.to_f
|
172
|
+
end
|
176
173
|
if r =~ /Complete requests:\s*(\d+)/
|
177
174
|
requests_completed = $1.to_i
|
178
175
|
end
|
@@ -181,11 +178,13 @@ class ServerTest
|
|
181
178
|
else
|
182
179
|
raise "didn't get how many failed requests from ab"
|
183
180
|
end
|
184
|
-
|
181
|
+
successful_requests = requests_completed - failed_requests
|
182
|
+
puts " #{rps} req/sec (#{requests_completed} total, #{failed_requests} failed in #{"%.2f" % time_taken} seconds)"
|
185
183
|
|
186
184
|
{
|
187
185
|
:server => @name,
|
188
186
|
:rps => rps,
|
187
|
+
:time_taken => time_taken,
|
189
188
|
:requests_completed => requests_completed,
|
190
189
|
:requests_failed => failed_requests,
|
191
190
|
:ab_cmd => cmd
|
data/bin/ebb_rails
CHANGED
File without changes
|
data/libev/ev.c
CHANGED
@@ -1,32 +1,40 @@
|
|
1
1
|
/*
|
2
2
|
* libev event processing core, watcher management
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
|
-
* Redistribution and use in source and binary forms, with or without
|
8
|
-
*
|
9
|
-
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without modifica-
|
8
|
+
* tion, are permitted provided that the following conditions are met:
|
9
|
+
*
|
10
|
+
* 1. Redistributions of source code must retain the above copyright notice,
|
11
|
+
* this list of conditions and the following disclaimer.
|
12
|
+
*
|
13
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
14
|
+
* notice, this list of conditions and the following disclaimer in the
|
15
|
+
* documentation and/or other materials provided with the distribution.
|
16
|
+
*
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
18
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
19
|
+
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
20
|
+
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
21
|
+
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
22
|
+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
23
|
+
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
24
|
+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
25
|
+
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
26
|
+
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
10
27
|
*
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
14
|
-
*
|
15
|
-
*
|
16
|
-
*
|
17
|
-
*
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
-
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
-
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
-
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
25
|
-
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
26
|
-
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
27
|
-
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28
|
-
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
* Alternatively, the contents of this file may be used under the terms of
|
29
|
+
* the GNU General Public License ("GPL") version 2 or any later version,
|
30
|
+
* in which case the provisions of the GPL are applicable instead of
|
31
|
+
* the above. If you wish to allow the use of your version of this file
|
32
|
+
* only under the terms of the GPL and not to allow others to use your
|
33
|
+
* version of this file under the BSD license, indicate your decision
|
34
|
+
* by deleting the provisions above and replace them with the notice
|
35
|
+
* and other provisions required by the GPL. If you do not delete the
|
36
|
+
* provisions above, a recipient may use your version of this file under
|
37
|
+
* either the BSD or the GPL.
|
30
38
|
*/
|
31
39
|
|
32
40
|
#ifdef __cplusplus
|
@@ -282,9 +290,11 @@ typedef ev_watcher *W;
|
|
282
290
|
typedef ev_watcher_list *WL;
|
283
291
|
typedef ev_watcher_time *WT;
|
284
292
|
|
293
|
+
#if EV_USE_MONOTONIC
|
285
294
|
/* sig_atomic_t is used to avoid per-thread variables or locking but still */
|
286
295
|
/* giving it a reasonably high chance of working on typical architetcures */
|
287
|
-
static
|
296
|
+
static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */
|
297
|
+
#endif
|
288
298
|
|
289
299
|
#ifdef _WIN32
|
290
300
|
# include "ev_win32.c"
|
@@ -443,7 +453,7 @@ ev_sleep (ev_tstamp delay)
|
|
443
453
|
|
444
454
|
nanosleep (&ts, 0);
|
445
455
|
#elif defined(_WIN32)
|
446
|
-
Sleep (delay * 1e3);
|
456
|
+
Sleep ((unsigned long)(delay * 1e3));
|
447
457
|
#else
|
448
458
|
struct timeval tv;
|
449
459
|
|
@@ -592,7 +602,11 @@ fd_reify (EV_P)
|
|
592
602
|
if (events)
|
593
603
|
{
|
594
604
|
unsigned long argp;
|
595
|
-
|
605
|
+
#ifdef EV_FD_TO_WIN32_HANDLE
|
606
|
+
anfd->handle = EV_FD_TO_WIN32_HANDLE (fd);
|
607
|
+
#else
|
608
|
+
anfd->handle = _get_osfhandle (fd);
|
609
|
+
#endif
|
596
610
|
assert (("libev only supports socket fds in this configuration", ioctlsocket (anfd->handle, FIONREAD, &argp) == 0));
|
597
611
|
}
|
598
612
|
#endif
|
@@ -751,15 +765,13 @@ adjustheap (WT *heap, int N, int k)
|
|
751
765
|
typedef struct
|
752
766
|
{
|
753
767
|
WL head;
|
754
|
-
|
768
|
+
EV_ATOMIC_T gotsig;
|
755
769
|
} ANSIG;
|
756
770
|
|
757
771
|
static ANSIG *signals;
|
758
772
|
static int signalmax;
|
759
773
|
|
760
|
-
static
|
761
|
-
static sig_atomic_t volatile gotsig;
|
762
|
-
static ev_io sigev;
|
774
|
+
static EV_ATOMIC_T gotsig;
|
763
775
|
|
764
776
|
void inline_size
|
765
777
|
signals_init (ANSIG *base, int count)
|
@@ -773,24 +785,102 @@ signals_init (ANSIG *base, int count)
|
|
773
785
|
}
|
774
786
|
}
|
775
787
|
|
776
|
-
|
777
|
-
|
788
|
+
/*****************************************************************************/
|
789
|
+
|
790
|
+
void inline_speed
|
791
|
+
fd_intern (int fd)
|
778
792
|
{
|
779
|
-
#
|
780
|
-
|
793
|
+
#ifdef _WIN32
|
794
|
+
int arg = 1;
|
795
|
+
ioctlsocket (_get_osfhandle (fd), FIONBIO, &arg);
|
796
|
+
#else
|
797
|
+
fcntl (fd, F_SETFD, FD_CLOEXEC);
|
798
|
+
fcntl (fd, F_SETFL, O_NONBLOCK);
|
781
799
|
#endif
|
800
|
+
}
|
782
801
|
|
783
|
-
|
802
|
+
static void noinline
|
803
|
+
evpipe_init (EV_P)
|
804
|
+
{
|
805
|
+
if (!ev_is_active (&pipeev))
|
806
|
+
{
|
807
|
+
while (pipe (evpipe))
|
808
|
+
syserr ("(libev) error creating signal/async pipe");
|
784
809
|
|
785
|
-
|
810
|
+
fd_intern (evpipe [0]);
|
811
|
+
fd_intern (evpipe [1]);
|
812
|
+
|
813
|
+
ev_io_set (&pipeev, evpipe [0], EV_READ);
|
814
|
+
ev_io_start (EV_A_ &pipeev);
|
815
|
+
ev_unref (EV_A); /* watcher should not keep loop alive */
|
816
|
+
}
|
817
|
+
}
|
818
|
+
|
819
|
+
void inline_size
|
820
|
+
evpipe_write (EV_P_ EV_ATOMIC_T *flag)
|
821
|
+
{
|
822
|
+
if (!*flag)
|
786
823
|
{
|
787
|
-
int old_errno = errno;
|
788
|
-
|
789
|
-
|
824
|
+
int old_errno = errno; /* save errno because write might clobber it */
|
825
|
+
|
826
|
+
*flag = 1;
|
827
|
+
write (evpipe [1], &old_errno, 1);
|
828
|
+
|
790
829
|
errno = old_errno;
|
791
830
|
}
|
792
831
|
}
|
793
832
|
|
833
|
+
static void
|
834
|
+
pipecb (EV_P_ ev_io *iow, int revents)
|
835
|
+
{
|
836
|
+
{
|
837
|
+
int dummy;
|
838
|
+
read (evpipe [0], &dummy, 1);
|
839
|
+
}
|
840
|
+
|
841
|
+
if (gotsig && ev_is_default_loop (EV_A))
|
842
|
+
{
|
843
|
+
int signum;
|
844
|
+
gotsig = 0;
|
845
|
+
|
846
|
+
for (signum = signalmax; signum--; )
|
847
|
+
if (signals [signum].gotsig)
|
848
|
+
ev_feed_signal_event (EV_A_ signum + 1);
|
849
|
+
}
|
850
|
+
|
851
|
+
#if EV_ASYNC_ENABLE
|
852
|
+
if (gotasync)
|
853
|
+
{
|
854
|
+
int i;
|
855
|
+
gotasync = 0;
|
856
|
+
|
857
|
+
for (i = asynccnt; i--; )
|
858
|
+
if (asyncs [i]->sent)
|
859
|
+
{
|
860
|
+
asyncs [i]->sent = 0;
|
861
|
+
ev_feed_event (EV_A_ asyncs [i], EV_ASYNC);
|
862
|
+
}
|
863
|
+
}
|
864
|
+
#endif
|
865
|
+
}
|
866
|
+
|
867
|
+
/*****************************************************************************/
|
868
|
+
|
869
|
+
static void
|
870
|
+
ev_sighandler (int signum)
|
871
|
+
{
|
872
|
+
#if EV_MULTIPLICITY
|
873
|
+
struct ev_loop *loop = &default_loop_struct;
|
874
|
+
#endif
|
875
|
+
|
876
|
+
#if _WIN32
|
877
|
+
signal (signum, ev_sighandler);
|
878
|
+
#endif
|
879
|
+
|
880
|
+
signals [signum - 1].gotsig = 1;
|
881
|
+
evpipe_write (EV_A_ &gotsig);
|
882
|
+
}
|
883
|
+
|
794
884
|
void noinline
|
795
885
|
ev_feed_signal_event (EV_P_ int signum)
|
796
886
|
{
|
@@ -811,42 +901,6 @@ ev_feed_signal_event (EV_P_ int signum)
|
|
811
901
|
ev_feed_event (EV_A_ (W)w, EV_SIGNAL);
|
812
902
|
}
|
813
903
|
|
814
|
-
static void
|
815
|
-
sigcb (EV_P_ ev_io *iow, int revents)
|
816
|
-
{
|
817
|
-
int signum;
|
818
|
-
|
819
|
-
read (sigpipe [0], &revents, 1);
|
820
|
-
gotsig = 0;
|
821
|
-
|
822
|
-
for (signum = signalmax; signum--; )
|
823
|
-
if (signals [signum].gotsig)
|
824
|
-
ev_feed_signal_event (EV_A_ signum + 1);
|
825
|
-
}
|
826
|
-
|
827
|
-
void inline_speed
|
828
|
-
fd_intern (int fd)
|
829
|
-
{
|
830
|
-
#ifdef _WIN32
|
831
|
-
int arg = 1;
|
832
|
-
ioctlsocket (_get_osfhandle (fd), FIONBIO, &arg);
|
833
|
-
#else
|
834
|
-
fcntl (fd, F_SETFD, FD_CLOEXEC);
|
835
|
-
fcntl (fd, F_SETFL, O_NONBLOCK);
|
836
|
-
#endif
|
837
|
-
}
|
838
|
-
|
839
|
-
static void noinline
|
840
|
-
siginit (EV_P)
|
841
|
-
{
|
842
|
-
fd_intern (sigpipe [0]);
|
843
|
-
fd_intern (sigpipe [1]);
|
844
|
-
|
845
|
-
ev_io_set (&sigev, sigpipe [0], EV_READ);
|
846
|
-
ev_io_start (EV_A_ &sigev);
|
847
|
-
ev_unref (EV_A); /* child watcher should not keep loop alive */
|
848
|
-
}
|
849
|
-
|
850
904
|
/*****************************************************************************/
|
851
905
|
|
852
906
|
static WL childs [EV_PID_HASHSIZE];
|
@@ -855,19 +909,27 @@ static WL childs [EV_PID_HASHSIZE];
|
|
855
909
|
|
856
910
|
static ev_signal childev;
|
857
911
|
|
912
|
+
#ifndef WIFCONTINUED
|
913
|
+
# define WIFCONTINUED(status) 0
|
914
|
+
#endif
|
915
|
+
|
858
916
|
void inline_speed
|
859
|
-
child_reap (EV_P_
|
917
|
+
child_reap (EV_P_ int chain, int pid, int status)
|
860
918
|
{
|
861
919
|
ev_child *w;
|
920
|
+
int traced = WIFSTOPPED (status) || WIFCONTINUED (status);
|
862
921
|
|
863
922
|
for (w = (ev_child *)childs [chain & (EV_PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next)
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
923
|
+
{
|
924
|
+
if ((w->pid == pid || !w->pid)
|
925
|
+
&& (!traced || (w->flags & 1)))
|
926
|
+
{
|
927
|
+
ev_set_priority (w, EV_MAXPRI); /* need to do it *now*, this *must* be the same prio as the signal watcher itself */
|
928
|
+
w->rpid = pid;
|
929
|
+
w->rstatus = status;
|
930
|
+
ev_feed_event (EV_A_ (W)w, EV_CHILD);
|
931
|
+
}
|
932
|
+
}
|
871
933
|
}
|
872
934
|
|
873
935
|
#ifndef WCONTINUED
|
@@ -886,13 +948,13 @@ childcb (EV_P_ ev_signal *sw, int revents)
|
|
886
948
|
|| 0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED)))
|
887
949
|
return;
|
888
950
|
|
889
|
-
/* make sure we are called again until all
|
951
|
+
/* make sure we are called again until all children have been reaped */
|
890
952
|
/* we need to do it this way so that the callback gets called before we continue */
|
891
953
|
ev_feed_event (EV_A_ (W)sw, EV_SIGNAL);
|
892
954
|
|
893
|
-
child_reap (EV_A_
|
955
|
+
child_reap (EV_A_ pid, pid, status);
|
894
956
|
if (EV_PID_HASHSIZE > 1)
|
895
|
-
child_reap (EV_A_
|
957
|
+
child_reap (EV_A_ 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */
|
896
958
|
}
|
897
959
|
|
898
960
|
#endif
|
@@ -1020,13 +1082,19 @@ loop_init (EV_P_ unsigned int flags)
|
|
1020
1082
|
}
|
1021
1083
|
#endif
|
1022
1084
|
|
1023
|
-
ev_rt_now
|
1024
|
-
mn_now
|
1025
|
-
now_floor
|
1026
|
-
rtmn_diff
|
1085
|
+
ev_rt_now = ev_time ();
|
1086
|
+
mn_now = get_clock ();
|
1087
|
+
now_floor = mn_now;
|
1088
|
+
rtmn_diff = ev_rt_now - mn_now;
|
1027
1089
|
|
1028
1090
|
io_blocktime = 0.;
|
1029
1091
|
timeout_blocktime = 0.;
|
1092
|
+
backend = 0;
|
1093
|
+
backend_fd = -1;
|
1094
|
+
gotasync = 0;
|
1095
|
+
#if EV_USE_INOTIFY
|
1096
|
+
fs_fd = -2;
|
1097
|
+
#endif
|
1030
1098
|
|
1031
1099
|
/* pid check not overridable via env */
|
1032
1100
|
#ifndef _WIN32
|
@@ -1042,12 +1110,6 @@ loop_init (EV_P_ unsigned int flags)
|
|
1042
1110
|
if (!(flags & 0x0000ffffUL))
|
1043
1111
|
flags |= ev_recommended_backends ();
|
1044
1112
|
|
1045
|
-
backend = 0;
|
1046
|
-
backend_fd = -1;
|
1047
|
-
#if EV_USE_INOTIFY
|
1048
|
-
fs_fd = -2;
|
1049
|
-
#endif
|
1050
|
-
|
1051
1113
|
#if EV_USE_PORT
|
1052
1114
|
if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
|
1053
1115
|
#endif
|
@@ -1064,8 +1126,8 @@ loop_init (EV_P_ unsigned int flags)
|
|
1064
1126
|
if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);
|
1065
1127
|
#endif
|
1066
1128
|
|
1067
|
-
ev_init (&
|
1068
|
-
ev_set_priority (&
|
1129
|
+
ev_init (&pipeev, pipecb);
|
1130
|
+
ev_set_priority (&pipeev, EV_MAXPRI);
|
1069
1131
|
}
|
1070
1132
|
}
|
1071
1133
|
|
@@ -1074,6 +1136,15 @@ loop_destroy (EV_P)
|
|
1074
1136
|
{
|
1075
1137
|
int i;
|
1076
1138
|
|
1139
|
+
if (ev_is_active (&pipeev))
|
1140
|
+
{
|
1141
|
+
ev_ref (EV_A); /* signal watcher */
|
1142
|
+
ev_io_stop (EV_A_ &pipeev);
|
1143
|
+
|
1144
|
+
close (evpipe [0]); evpipe [0] = 0;
|
1145
|
+
close (evpipe [1]); evpipe [1] = 0;
|
1146
|
+
}
|
1147
|
+
|
1077
1148
|
#if EV_USE_INOTIFY
|
1078
1149
|
if (fs_fd >= 0)
|
1079
1150
|
close (fs_fd);
|
@@ -1119,6 +1190,9 @@ loop_destroy (EV_P)
|
|
1119
1190
|
#endif
|
1120
1191
|
array_free (prepare, EMPTY);
|
1121
1192
|
array_free (check, EMPTY);
|
1193
|
+
#if EV_ASYNC_ENABLE
|
1194
|
+
array_free (async, EMPTY);
|
1195
|
+
#endif
|
1122
1196
|
|
1123
1197
|
backend = 0;
|
1124
1198
|
}
|
@@ -1141,19 +1215,23 @@ loop_fork (EV_P)
|
|
1141
1215
|
infy_fork (EV_A);
|
1142
1216
|
#endif
|
1143
1217
|
|
1144
|
-
if (ev_is_active (&
|
1218
|
+
if (ev_is_active (&pipeev))
|
1145
1219
|
{
|
1146
|
-
/*
|
1220
|
+
/* this "locks" the handlers against writing to the pipe */
|
1221
|
+
/* while we modify the fd vars */
|
1222
|
+
gotsig = 1;
|
1223
|
+
#if EV_ASYNC_ENABLE
|
1224
|
+
gotasync = 1;
|
1225
|
+
#endif
|
1147
1226
|
|
1148
1227
|
ev_ref (EV_A);
|
1149
|
-
ev_io_stop (EV_A_ &
|
1150
|
-
close (
|
1151
|
-
close (
|
1152
|
-
|
1153
|
-
while (pipe (sigpipe))
|
1154
|
-
syserr ("(libev) error creating pipe");
|
1228
|
+
ev_io_stop (EV_A_ &pipeev);
|
1229
|
+
close (evpipe [0]);
|
1230
|
+
close (evpipe [1]);
|
1155
1231
|
|
1156
|
-
|
1232
|
+
evpipe_init (EV_A);
|
1233
|
+
/* now iterate over everything, in case we missed something */
|
1234
|
+
pipecb (EV_A_ &pipeev, EV_READ);
|
1157
1235
|
}
|
1158
1236
|
|
1159
1237
|
postfork = 0;
|
@@ -1185,7 +1263,7 @@ ev_loop_destroy (EV_P)
|
|
1185
1263
|
void
|
1186
1264
|
ev_loop_fork (EV_P)
|
1187
1265
|
{
|
1188
|
-
postfork = 1;
|
1266
|
+
postfork = 1; /* must be in line with ev_default_fork */
|
1189
1267
|
}
|
1190
1268
|
|
1191
1269
|
#endif
|
@@ -1198,10 +1276,6 @@ int
|
|
1198
1276
|
ev_default_loop (unsigned int flags)
|
1199
1277
|
#endif
|
1200
1278
|
{
|
1201
|
-
if (sigpipe [0] == sigpipe [1])
|
1202
|
-
if (pipe (sigpipe))
|
1203
|
-
return 0;
|
1204
|
-
|
1205
1279
|
if (!ev_default_loop_ptr)
|
1206
1280
|
{
|
1207
1281
|
#if EV_MULTIPLICITY
|
@@ -1214,8 +1288,6 @@ ev_default_loop (unsigned int flags)
|
|
1214
1288
|
|
1215
1289
|
if (ev_backend (EV_A))
|
1216
1290
|
{
|
1217
|
-
siginit (EV_A);
|
1218
|
-
|
1219
1291
|
#ifndef _WIN32
|
1220
1292
|
ev_signal_init (&childev, childcb, SIGCHLD);
|
1221
1293
|
ev_set_priority (&childev, EV_MAXPRI);
|
@@ -1242,12 +1314,6 @@ ev_default_destroy (void)
|
|
1242
1314
|
ev_signal_stop (EV_A_ &childev);
|
1243
1315
|
#endif
|
1244
1316
|
|
1245
|
-
ev_ref (EV_A); /* signal watcher */
|
1246
|
-
ev_io_stop (EV_A_ &sigev);
|
1247
|
-
|
1248
|
-
close (sigpipe [0]); sigpipe [0] = 0;
|
1249
|
-
close (sigpipe [1]); sigpipe [1] = 0;
|
1250
|
-
|
1251
1317
|
loop_destroy (EV_A);
|
1252
1318
|
}
|
1253
1319
|
|
@@ -1259,7 +1325,7 @@ ev_default_fork (void)
|
|
1259
1325
|
#endif
|
1260
1326
|
|
1261
1327
|
if (backend)
|
1262
|
-
postfork = 1;
|
1328
|
+
postfork = 1; /* must be in line with ev_loop_fork */
|
1263
1329
|
}
|
1264
1330
|
|
1265
1331
|
/*****************************************************************************/
|
@@ -1478,9 +1544,7 @@ static int loop_done;
|
|
1478
1544
|
void
|
1479
1545
|
ev_loop (EV_P_ int flags)
|
1480
1546
|
{
|
1481
|
-
loop_done =
|
1482
|
-
? EVUNLOOP_ONE
|
1483
|
-
: EVUNLOOP_CANCEL;
|
1547
|
+
loop_done = EVUNLOOP_CANCEL;
|
1484
1548
|
|
1485
1549
|
call_pending (EV_A); /* in case we recurse, ensure ordering stays nice and clean */
|
1486
1550
|
|
@@ -1586,9 +1650,12 @@ ev_loop (EV_P_ int flags)
|
|
1586
1650
|
queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
|
1587
1651
|
|
1588
1652
|
call_pending (EV_A);
|
1589
|
-
|
1590
1653
|
}
|
1591
|
-
while (expect_true (
|
1654
|
+
while (expect_true (
|
1655
|
+
activecnt
|
1656
|
+
&& !loop_done
|
1657
|
+
&& !(flags & (EVLOOP_ONESHOT | EVLOOP_NONBLOCK))
|
1658
|
+
));
|
1592
1659
|
|
1593
1660
|
if (loop_done == EVUNLOOP_ONE)
|
1594
1661
|
loop_done = EVUNLOOP_CANCEL;
|
@@ -1844,6 +1911,8 @@ ev_signal_start (EV_P_ ev_signal *w)
|
|
1844
1911
|
|
1845
1912
|
assert (("ev_signal_start called with illegal signal number", w->signum > 0));
|
1846
1913
|
|
1914
|
+
evpipe_init (EV_A);
|
1915
|
+
|
1847
1916
|
{
|
1848
1917
|
#ifndef _WIN32
|
1849
1918
|
sigset_t full, prev;
|
@@ -1864,10 +1933,10 @@ ev_signal_start (EV_P_ ev_signal *w)
|
|
1864
1933
|
if (!((WL)w)->next)
|
1865
1934
|
{
|
1866
1935
|
#if _WIN32
|
1867
|
-
signal (w->signum,
|
1936
|
+
signal (w->signum, ev_sighandler);
|
1868
1937
|
#else
|
1869
1938
|
struct sigaction sa;
|
1870
|
-
sa.sa_handler =
|
1939
|
+
sa.sa_handler = ev_sighandler;
|
1871
1940
|
sigfillset (&sa.sa_mask);
|
1872
1941
|
sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */
|
1873
1942
|
sigaction (w->signum, &sa, 0);
|
@@ -2366,6 +2435,44 @@ ev_fork_stop (EV_P_ ev_fork *w)
|
|
2366
2435
|
}
|
2367
2436
|
#endif
|
2368
2437
|
|
2438
|
+
#if EV_ASYNC_ENABLE
|
2439
|
+
void
|
2440
|
+
ev_async_start (EV_P_ ev_async *w)
|
2441
|
+
{
|
2442
|
+
if (expect_false (ev_is_active (w)))
|
2443
|
+
return;
|
2444
|
+
|
2445
|
+
evpipe_init (EV_A);
|
2446
|
+
|
2447
|
+
ev_start (EV_A_ (W)w, ++asynccnt);
|
2448
|
+
array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2);
|
2449
|
+
asyncs [asynccnt - 1] = w;
|
2450
|
+
}
|
2451
|
+
|
2452
|
+
void
|
2453
|
+
ev_async_stop (EV_P_ ev_async *w)
|
2454
|
+
{
|
2455
|
+
clear_pending (EV_A_ (W)w);
|
2456
|
+
if (expect_false (!ev_is_active (w)))
|
2457
|
+
return;
|
2458
|
+
|
2459
|
+
{
|
2460
|
+
int active = ((W)w)->active;
|
2461
|
+
asyncs [active - 1] = asyncs [--asynccnt];
|
2462
|
+
((W)asyncs [active - 1])->active = active;
|
2463
|
+
}
|
2464
|
+
|
2465
|
+
ev_stop (EV_A_ (W)w);
|
2466
|
+
}
|
2467
|
+
|
2468
|
+
void
|
2469
|
+
ev_async_send (EV_P_ ev_async *w)
|
2470
|
+
{
|
2471
|
+
w->sent = 1;
|
2472
|
+
evpipe_write (EV_A_ &gotasync);
|
2473
|
+
}
|
2474
|
+
#endif
|
2475
|
+
|
2369
2476
|
/*****************************************************************************/
|
2370
2477
|
|
2371
2478
|
struct ev_once
|