<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,2 +1,2 @@
 * BUG: hangs on file upload 1 time out of 2
-* disable timeout when calling the Rack app
\ No newline at end of file
+* BUG: crash in Rails multipart parsing on big file upload
\ No newline at end of file</diff>
      <filename>TODO</filename>
    </modified>
    <modified>
      <diff>@@ -9,6 +9,11 @@ static void backend_accept_cb(EV_P_ struct ev_io *watcher, int revents)
   socklen_t          sin_size = sizeof(remote_addr);
   int                fd, flags;
   
+  if (EV_ERROR &amp; revents) {
+    rb_sys_fail(&quot;Error on acceptor socket&quot;);
+    return;
+  }
+  
   fd = accept(backend-&gt;fd, (struct sockaddr *)&amp;remote_addr, &amp;sin_size);
   if (fd == -1) {
     log_errno(backend);
@@ -83,7 +88,7 @@ VALUE backend_listen_on_port(VALUE self, VALUE address, VALUE port)
   if (setsockopt(backend-&gt;fd, SOL_SOCKET, SO_REUSEADDR, &amp;sock_flags, sizeof(sock_flags)) == -1)
     rb_sys_fail(&quot;setsockopt(SO_REUSEADDR)&quot;);
   
-  if (bind(backend-&gt;fd, (struct sockaddr *)&amp;backend-&gt;local_addr, sizeof backend-&gt;local_addr) == -1)
+  if (bind(backend-&gt;fd, (struct sockaddr *)&amp;backend-&gt;local_addr, sizeof(backend-&gt;local_addr)) == -1)
     rb_sys_fail(&quot;bind&quot;);
 
   if (listen(backend-&gt;fd, LISTEN_BACKLOG) == -1)
@@ -91,7 +96,7 @@ VALUE backend_listen_on_port(VALUE self, VALUE address, VALUE port)
   
   /* initialise watchers */
   backend-&gt;accept_watcher.data = backend;
-  ev_io_init(&amp;backend-&gt;accept_watcher, backend_accept_cb, backend-&gt;fd, EV_READ);
+  ev_io_init(&amp;backend-&gt;accept_watcher, backend_accept_cb, backend-&gt;fd, EV_READ | EV_ERROR);
   
   backend-&gt;prepare_watcher.data = backend;
   ev_prepare_init(&amp;backend-&gt;prepare_watcher, backend_prepare_cb);</diff>
      <filename>ext/thin_backend/backend.c</filename>
    </modified>
    <modified>
      <diff>@@ -12,6 +12,11 @@ static void connection_writable_cb(EV_P_ struct ev_io *watcher, int revents)
   connection_t *c = get_ev_data(connection, watcher, write);
   int           sent;
   
+  if (EV_ERROR &amp; revents) {
+    connection_error(c, &quot;Error writing on connection socket&quot;);
+    return;
+  }
+  
   if (c-&gt;write_buffer.len == 0)
     return;
   
@@ -44,6 +49,7 @@ static void connection_writable_cb(EV_P_ struct ev_io *watcher, int revents)
 void connection_watch_writable(connection_t *c)
 {
   ev_io_start(c-&gt;loop, &amp;c-&gt;write_watcher);
+  ev_timer_start(c-&gt;loop, &amp;c-&gt;timeout_watcher);
 }
 
 static void connection_readable_cb(EV_P_ struct ev_io *watcher, int revents)
@@ -52,6 +58,11 @@ static void connection_readable_cb(EV_P_ struct ev_io *watcher, int revents)
   size_t        n;
   char          buf[BUFFER_CHUNK_SIZE];
   
+  if (EV_ERROR &amp; revents) {
+    connection_error(c, &quot;Error reading on connection socket&quot;);
+    return;
+  }
+  
   n = recv(c-&gt;fd, buf, BUFFER_CHUNK_SIZE, 0);
   ev_timer_again(c-&gt;loop, &amp;c-&gt;timeout_watcher);
   
@@ -115,8 +126,8 @@ void connection_start(backend_t *backend, int fd, struct sockaddr_in remote_addr
   c-&gt;read_watcher.data    = c;
   c-&gt;write_watcher.data   = c;
   c-&gt;timeout_watcher.data = c;
-  ev_io_init(&amp;c-&gt;read_watcher, connection_readable_cb, c-&gt;fd, EV_READ);
-  ev_io_init(&amp;c-&gt;write_watcher, connection_writable_cb, c-&gt;fd, EV_WRITE);
+  ev_io_init(&amp;c-&gt;read_watcher, connection_readable_cb, c-&gt;fd, EV_READ | EV_ERROR);
+  ev_io_init(&amp;c-&gt;write_watcher, connection_writable_cb, c-&gt;fd, EV_WRITE | EV_ERROR);
   ev_timer_init(&amp;c-&gt;timeout_watcher, connection_timeout_cb, backend-&gt;timeout, backend-&gt;timeout);
   
   /* start event watchers */
@@ -124,17 +135,6 @@ void connection_start(backend_t *backend, int fd, struct sockaddr_in remote_addr
   ev_io_start(c-&gt;loop, &amp;c-&gt;read_watcher);
 }
 
-void connection_error(connection_t *c, const char *msg)
-{
-  log_error(c-&gt;backend, msg);
-  connection_close(c);
-}
-
-void connection_errno(connection_t *c)
-{
-  connection_error(c, strerror(errno));
-}
-
 void connection_close(connection_t *c)
 {
   ev_io_stop(c-&gt;loop, &amp;c-&gt;read_watcher);</diff>
      <filename>ext/thin_backend/connection.c</filename>
    </modified>
    <modified>
      <diff>@@ -62,6 +62,7 @@ void request_parse(connection_t *c, char *buf, int len)
   
   /* request fully received */
   if (http_parser_is_finished(&amp;c-&gt;parser) &amp;&amp; c-&gt;read_buffer.len &gt;= c-&gt;content_length) {
+    ev_timer_stop(c-&gt;loop, &amp;c-&gt;timeout_watcher);
     ev_io_stop(c-&gt;loop, &amp;c-&gt;read_watcher);
     
     /* assign env[rack.input] */</diff>
      <filename>ext/thin_backend/request.c</filename>
    </modified>
    <modified>
      <diff>@@ -123,9 +123,10 @@ void backend_define(void);
 
 /* connection */
 void connection_start(backend_t *backend, int fd, struct sockaddr_in remote_addr);
-void connection_error(connection_t *c, const char *msg);
-void connection_errno(connection_t *c);
 void connection_close(connection_t *connection);
+/* error handling macros (so we can get line number and stuff) */
+#define connection_error(c, msg) log_error((c)-&gt;backend, msg); connection_close(c)
+#define connection_errno(c) connection_error(c, strerror(errno))
 
 /* request &amp; response */
 void request_parse(connection_t *connection, char *buf, int len);</diff>
      <filename>ext/thin_backend/thin.h</filename>
    </modified>
    <modified>
      <diff>@@ -17,7 +17,7 @@ class App
   def call(env)
     sleep 10 if env['PATH_INFO'] == '/slow'
     
-    # puts env['rack.input'].read if env['CONTENT_LENGTH'].to_i &gt; 0
+    puts env['rack.input'].read.size if env['CONTENT_LENGTH'].to_i &gt; 0
     [
       200,
       {</diff>
      <filename>script/app.ru</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>abdd36a52b9d48107b12ecec4f275512c2b49cfd</id>
    </parent>
  </parents>
  <author>
    <name>macournoyer</name>
    <email>macournoyer@gmail.com</email>
  </author>
  <url>http://github.com/macournoyer/thin-turbo/commit/3617273054daa8b164aafc4568f1ff822ff16075</url>
  <id>3617273054daa8b164aafc4568f1ff822ff16075</id>
  <committed-date>2008-06-02T18:51:41-07:00</committed-date>
  <authored-date>2008-06-02T18:51:41-07:00</authored-date>
  <message>disable timeout when calling the Rack app
handle EV_ERROR in event callbacks</message>
  <tree>4579d3642cc08d6156f8796bedf7f5bda2839a1a</tree>
  <committer>
    <name>macournoyer</name>
    <email>macournoyer@gmail.com</email>
  </committer>
</commit>
