public
Description: New and ultra-turbo-crazy-fast backend for Thin
Homepage: http://code.macournoyer.com/thin/
Clone URL: git://github.com/macournoyer/thin-turbo.git
disable timeout when calling the Rack app
handle EV_ERROR in event callbacks
macournoyer (author)
Mon Jun 02 18:51:41 -0700 2008
commit  3617273054daa8b164aafc4568f1ff822ff16075
tree    4579d3642cc08d6156f8796bedf7f5bda2839a1a
parent  abdd36a52b9d48107b12ecec4f275512c2b49cfd
0
...
1
2
3
 
4
...
1
 
2
3
4
0
@@ -1,2 +1,2 @@
0
 * BUG: hangs on file upload 1 time out of 2
0
-* disable timeout when calling the Rack app
0
\ No newline at end of file
0
+* BUG: crash in Rails multipart parsing on big file upload
0
\ No newline at end of file
...
9
10
11
 
 
 
 
 
12
13
14
...
83
84
85
86
 
87
88
89
...
91
92
93
94
 
95
96
97
...
9
10
11
12
13
14
15
16
17
18
19
...
88
89
90
 
91
92
93
94
...
96
97
98
 
99
100
101
102
0
@@ -9,6 +9,11 @@ static void backend_accept_cb(EV_P_ struct ev_io *watcher, int revents)
0
   socklen_t sin_size = sizeof(remote_addr);
0
   int fd, flags;
0
   
0
+ if (EV_ERROR & revents) {
0
+ rb_sys_fail("Error on acceptor socket");
0
+ return;
0
+ }
0
+
0
   fd = accept(backend->fd, (struct sockaddr *)&remote_addr, &sin_size);
0
   if (fd == -1) {
0
     log_errno(backend);
0
@@ -83,7 +88,7 @@ VALUE backend_listen_on_port(VALUE self, VALUE address, VALUE port)
0
   if (setsockopt(backend->fd, SOL_SOCKET, SO_REUSEADDR, &sock_flags, sizeof(sock_flags)) == -1)
0
     rb_sys_fail("setsockopt(SO_REUSEADDR)");
0
   
0
- if (bind(backend->fd, (struct sockaddr *)&backend->local_addr, sizeof backend->local_addr) == -1)
0
+ if (bind(backend->fd, (struct sockaddr *)&backend->local_addr, sizeof(backend->local_addr)) == -1)
0
     rb_sys_fail("bind");
0
 
0
   if (listen(backend->fd, LISTEN_BACKLOG) == -1)
0
@@ -91,7 +96,7 @@ VALUE backend_listen_on_port(VALUE self, VALUE address, VALUE port)
0
   
0
   /* initialise watchers */
0
   backend->accept_watcher.data = backend;
0
- ev_io_init(&backend->accept_watcher, backend_accept_cb, backend->fd, EV_READ);
0
+ ev_io_init(&backend->accept_watcher, backend_accept_cb, backend->fd, EV_READ | EV_ERROR);
0
   
0
   backend->prepare_watcher.data = backend;
0
   ev_prepare_init(&backend->prepare_watcher, backend_prepare_cb);
...
12
13
14
 
 
 
 
 
15
16
17
...
44
45
46
 
47
48
49
...
52
53
54
 
 
 
 
 
55
56
57
...
115
116
117
118
119
 
 
120
121
122
...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
12
13
14
15
16
17
18
19
20
21
22
...
49
50
51
52
53
54
55
...
58
59
60
61
62
63
64
65
66
67
68
...
126
127
128
 
 
129
130
131
132
133
...
135
136
137
 
 
 
 
 
 
 
 
 
 
 
138
139
140
0
@@ -12,6 +12,11 @@ static void connection_writable_cb(EV_P_ struct ev_io *watcher, int revents)
0
   connection_t *c = get_ev_data(connection, watcher, write);
0
   int sent;
0
   
0
+ if (EV_ERROR & revents) {
0
+ connection_error(c, "Error writing on connection socket");
0
+ return;
0
+ }
0
+
0
   if (c->write_buffer.len == 0)
0
     return;
0
   
0
@@ -44,6 +49,7 @@ static void connection_writable_cb(EV_P_ struct ev_io *watcher, int revents)
0
 void connection_watch_writable(connection_t *c)
0
 {
0
   ev_io_start(c->loop, &c->write_watcher);
0
+ ev_timer_start(c->loop, &c->timeout_watcher);
0
 }
0
 
0
 static void connection_readable_cb(EV_P_ struct ev_io *watcher, int revents)
0
@@ -52,6 +58,11 @@ static void connection_readable_cb(EV_P_ struct ev_io *watcher, int revents)
0
   size_t n;
0
   char buf[BUFFER_CHUNK_SIZE];
0
   
0
+ if (EV_ERROR & revents) {
0
+ connection_error(c, "Error reading on connection socket");
0
+ return;
0
+ }
0
+
0
   n = recv(c->fd, buf, BUFFER_CHUNK_SIZE, 0);
0
   ev_timer_again(c->loop, &c->timeout_watcher);
0
   
0
@@ -115,8 +126,8 @@ void connection_start(backend_t *backend, int fd, struct sockaddr_in remote_addr
0
   c->read_watcher.data = c;
0
   c->write_watcher.data = c;
0
   c->timeout_watcher.data = c;
0
- ev_io_init(&c->read_watcher, connection_readable_cb, c->fd, EV_READ);
0
- ev_io_init(&c->write_watcher, connection_writable_cb, c->fd, EV_WRITE);
0
+ ev_io_init(&c->read_watcher, connection_readable_cb, c->fd, EV_READ | EV_ERROR);
0
+ ev_io_init(&c->write_watcher, connection_writable_cb, c->fd, EV_WRITE | EV_ERROR);
0
   ev_timer_init(&c->timeout_watcher, connection_timeout_cb, backend->timeout, backend->timeout);
0
   
0
   /* start event watchers */
0
@@ -124,17 +135,6 @@ void connection_start(backend_t *backend, int fd, struct sockaddr_in remote_addr
0
   ev_io_start(c->loop, &c->read_watcher);
0
 }
0
 
0
-void connection_error(connection_t *c, const char *msg)
0
-{
0
- log_error(c->backend, msg);
0
- connection_close(c);
0
-}
0
-
0
-void connection_errno(connection_t *c)
0
-{
0
- connection_error(c, strerror(errno));
0
-}
0
-
0
 void connection_close(connection_t *c)
0
 {
0
   ev_io_stop(c->loop, &c->read_watcher);
...
62
63
64
 
65
66
67
...
62
63
64
65
66
67
68
0
@@ -62,6 +62,7 @@ void request_parse(connection_t *c, char *buf, int len)
0
   
0
   /* request fully received */
0
   if (http_parser_is_finished(&c->parser) && c->read_buffer.len >= c->content_length) {
0
+ ev_timer_stop(c->loop, &c->timeout_watcher);
0
     ev_io_stop(c->loop, &c->read_watcher);
0
     
0
     /* assign env[rack.input] */
...
123
124
125
126
127
128
 
 
 
129
130
131
...
123
124
125
 
 
126
127
128
129
130
131
132
0
@@ -123,9 +123,10 @@ void backend_define(void);
0
 
0
 /* connection */
0
 void connection_start(backend_t *backend, int fd, struct sockaddr_in remote_addr);
0
-void connection_error(connection_t *c, const char *msg);
0
-void connection_errno(connection_t *c);
0
 void connection_close(connection_t *connection);
0
+/* error handling macros (so we can get line number and stuff) */
0
+#define connection_error(c, msg) log_error((c)->backend, msg); connection_close(c)
0
+#define connection_errno(c) connection_error(c, strerror(errno))
0
 
0
 /* request & response */
0
 void request_parse(connection_t *connection, char *buf, int len);
...
17
18
19
20
 
21
22
23
...
17
18
19
 
20
21
22
23
0
@@ -17,7 +17,7 @@ class App
0
   def call(env)
0
     sleep 10 if env['PATH_INFO'] == '/slow'
0
     
0
- # puts env['rack.input'].read if env['CONTENT_LENGTH'].to_i > 0
0
+ puts env['rack.input'].read.size if env['CONTENT_LENGTH'].to_i > 0
0
     [
0
       200,
0
       {

Comments

    No one has commented yet.