diff -rNU 30 ../httpd-2.2.12-o/modules/ssl/ssl_engine_io.c ./modules/ssl/ssl_engine_io.c
--- ../httpd-2.2.12-o/modules/ssl/ssl_engine_io.c	2013-04-26 19:51:20.000000000 +0200
+++ ./modules/ssl/ssl_engine_io.c	2013-04-26 20:05:58.000000000 +0200
@@ -1358,63 +1358,72 @@
     /* XXX: we could actually move ssl_io_filter_connect to an
      * ap_hook_process_connection but would still need to call it for
      * AP_MODE_INIT for protocols that may upgrade the connection
      * rather than have SSLEngine On configured.
      */
     if ((status = ssl_io_filter_connect(inctx->filter_ctx)) != APR_SUCCESS) {
         return ssl_io_filter_error(f, bb, status);
     }
 
     if (is_init) {
         /* protocol module needs to handshake before sending
          * data to client (e.g. NNTP or FTP)
          */
         return APR_SUCCESS;
     }
 
     if (inctx->mode == AP_MODE_READBYTES ||
         inctx->mode == AP_MODE_SPECULATIVE) {
         /* Protected from truncation, readbytes < MAX_SIZE_T
          * FIXME: No, it's *not* protected.  -- jre */
         if (readbytes < len) {
             len = (apr_size_t)readbytes;
         }
         status = ssl_io_input_read(inctx, inctx->buffer, &len);
     }
     else if (inctx->mode == AP_MODE_GETLINE) {
         status = ssl_io_input_getline(inctx, inctx->buffer, &len);
     }
     else {
         /* We have no idea what you are talking about, so return an error. */
-        return APR_ENOTIMPL;
+        status = APR_ENOTIMPL;
     }
 
+    /* It is possible for mod_ssl's BIO to be used outside of the
+     * direct control of mod_ssl's input or output filter -- notably,
+     * when mod_ssl initiates a renegotiation.  Switching the BIO mode
+     * back to "blocking" here ensures such operations don't fail with
+     * SSL_ERROR_WANT_READ. */
+    inctx->block = APR_BLOCK_READ;
+
+    /* Handle custom errors. */
+
     if (status != APR_SUCCESS) {
         return ssl_io_filter_error(f, bb, status);
     }
 
     /* Create a transient bucket out of the decrypted data. */
     if (len > 0) {
         apr_bucket *bucket =
             apr_bucket_transient_create(inctx->buffer, len, f->c->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(bb, bucket);
     }
 
     return APR_SUCCESS;
 }
 
 static apr_status_t ssl_io_filter_output(ap_filter_t *f,
                                          apr_bucket_brigade *bb)
 {
     apr_status_t status = APR_SUCCESS;
     ssl_filter_ctx_t *filter_ctx = f->ctx;
     bio_filter_in_ctx_t *inctx;
     bio_filter_out_ctx_t *outctx;
     apr_read_type_e rblock = APR_NONBLOCK_READ;
 
     if (f->c->aborted) {
         apr_brigade_cleanup(bb);
         return APR_ECONNABORTED;
     }
 
     if (!filter_ctx->pssl) {
         /* ssl_filter_io_shutdown was called */
@@ -1665,61 +1674,61 @@
         /* Partition the buffered brigade. */
         rv = apr_brigade_partition(ctx->bb, bytes, &e);
         if (rv && rv != APR_INCOMPLETE) {
             ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c,
                           "could not partition buffered SSL brigade");
             ap_remove_input_filter(f);
             return rv;
         }
 
         /* If the buffered brigade contains less then the requested
          * length, just pass it all back. */
         if (rv == APR_INCOMPLETE) {
             APR_BRIGADE_CONCAT(bb, ctx->bb);
         } else {
             apr_bucket *d = APR_BRIGADE_FIRST(ctx->bb);
 
             e = APR_BUCKET_PREV(e);
 
             /* Unsplice the partitioned segment and move it into the
              * passed-in brigade; no convenient way to do this with
              * the APR_BRIGADE_* macros. */
             APR_RING_UNSPLICE(d, e, link);
             APR_RING_SPLICE_HEAD(&bb->list, d, e, apr_bucket, link);
 
             APR_BRIGADE_CHECK_CONSISTENCY(bb);
             APR_BRIGADE_CHECK_CONSISTENCY(ctx->bb);
         }
     }
     else {
         /* Split a line into the passed-in brigade. */
-        rv = apr_brigade_split_line(bb, ctx->bb, mode, bytes);
+        rv = apr_brigade_split_line(bb, ctx->bb, block, bytes);
 
         if (rv) {
             ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c,
                           "could not split line from buffered SSL brigade");
             ap_remove_input_filter(f);
             return rv;
         }
     }
 
     if (APR_BRIGADE_EMPTY(ctx->bb)) {
         apr_bucket *e = APR_BRIGADE_LAST(bb);
 
         /* Ensure that the brigade is terminated by an EOS if the
          * buffered request body has been entirely consumed. */
         if (e == APR_BRIGADE_SENTINEL(bb) || !APR_BUCKET_IS_EOS(e)) {
             e = apr_bucket_eos_create(f->c->bucket_alloc);
             APR_BRIGADE_INSERT_TAIL(bb, e);
         }
 
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c,
                       "buffered SSL brigade exhausted");
         /* Note that the filter must *not* be removed here; it may be
          * invoked again, see comment above. */
     }
 
     return APR_SUCCESS;
 }
 
 static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c,
                                     SSL *ssl)
