Could you try with the attached patch, and with only the problematic
client running? What does it log (the beginning of the session until it
starts repeating the same lines)?
On Sat, 2012-11-24 at 00:16 -0800, Erik A Johnson wrote:
> Thanks, Timo. Nope, still an infinite loop. Anything I can try using gdb to
> trace?
>
>
> On Nov 22, 2012, at 10:52 PM, Timo Sirainen <[email protected]> wrote:
>
> > On 10.11.2012, at 12.44, Erik A Johnson wrote:
> >
> >> imap-login processes are hanging (using 100% of CPU) when connected from a
> >> client that is partially blocked by a firewall. It appears that
> >> imap-login is stuck in a loop trying to complete an ssl handshake.
> >> imap-login is working fine for other clients not blocked by the firewall
> >> (including localhost).
> >>
> >> This is dovecot 2.1.10 under Mac OS X 10.8.2 (compiled from sources); the
> >> firewall is Little Snitch 3.0.1 blocking port 993, which appears to let
> >> the connection initiate but then squashes and disconnects the socket
> >> during ssl handshaking.
> >>
> >> gdb backtrace and Activity Monitor's "Sample Process" show that imap-login
> >> is stuck calling ioloop-kqueue's io_loop_handler_run -> io_loop_call_io ->
> >> ssl_step repeatedly; dtruss shows that it is repeatedly making system
> >> calls to kevent and read, the latter returning -1 with errno
> >> 57=ENOTCONN="Socket is not connected". (I also tried ./configure
> >> --with-ioloop=poll and --with-iopoll=select instead of the default best =
> >> kqueue but the results were the same; --with-iopoll=epoll didn't work
> >> because epoll is not available on this machine.) The client, initiated by
> >> the command "openssl s_client -connect SERVER:993", first responds
> >> "CONNECTED(00000003)" but then immediately the error
> >> "60278:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake
> >> failure:/SourceCache/OpenSSL098/OpenSSL098-44/src/ssl/s23_lib.c:182:".
> >> The infinite loop is in src/lib/ioloop.c in the function "io_loop_run"
> >> where the statement "while (ioloop->running) io_loop_handler_run(ioloop)"
> >> is executed.
> >
> > I wonder if this fixes it?
> > http://hg.dovecot.org/dovecot-2.1/rev/e95479f439aa
> >
>
diff -r 174d7e974326 src/login-common/ssl-proxy-openssl.c
--- a/src/login-common/ssl-proxy-openssl.c Tue Nov 27 09:13:57 2012 +0200
+++ b/src/login-common/ssl-proxy-openssl.c Tue Nov 27 09:17:03 2012 +0200
@@ -108,6 +108,7 @@
static void ssl_read(struct ssl_proxy *proxy);
static void ssl_write(struct ssl_proxy *proxy);
static void ssl_step(struct ssl_proxy *proxy);
+static void ssl_step_write(struct ssl_proxy *proxy);
static void ssl_proxy_destroy(struct ssl_proxy *proxy);
static void ssl_proxy_unref(struct ssl_proxy *proxy);
@@ -248,6 +249,7 @@
static void ssl_set_io(struct ssl_proxy *proxy, enum ssl_io_action action)
{
+ i_debug("ssl_set_io(%d)", action);
switch (action) {
case SSL_ADD_INPUT:
if (proxy->io_ssl_read != NULL)
@@ -263,7 +265,7 @@
if (proxy->io_ssl_write != NULL)
break;
proxy->io_ssl_write = io_add(proxy->fd_ssl, IO_WRITE,
- ssl_step, proxy);
+ ssl_step_write, proxy);
break;
case SSL_REMOVE_OUTPUT:
if (proxy->io_ssl_write != NULL)
@@ -404,12 +406,15 @@
i_free_and_null(proxy->last_error);
err = SSL_get_error(proxy->ssl, ret);
+ i_debug("SSL_get_error() = %d", err);
switch (err) {
case SSL_ERROR_WANT_READ:
+ i_debug(" - want_read");
ssl_set_io(proxy, SSL_ADD_INPUT);
break;
case SSL_ERROR_WANT_WRITE:
+ i_debug(" - want_write");
ssl_set_io(proxy, SSL_ADD_OUTPUT);
break;
case SSL_ERROR_SYSCALL:
@@ -463,6 +468,7 @@
}
} else {
ret = SSL_accept(proxy->ssl);
+ i_debug("ssl_handshake: SSL_accept()=%d", ret);
if (ret != 1) {
ssl_handle_error(proxy, ret, "SSL_accept()");
return;
@@ -520,8 +526,15 @@
}
}
+static void ssl_step_write(struct ssl_proxy *proxy)
+{
+ i_debug("ssl_step_write()");
+ ssl_step(proxy);
+}
+
static void ssl_step(struct ssl_proxy *proxy)
{
+ i_debug("ssl_step()");
proxy->refcount++;
if (!proxy->handshaked)