[Dovecot] [PATCH] net_connect_*(): Wait for fd to complete connect(2) when fd is non-blocking
Hi, Dovecot ignores EINPROGRESS on connect(2) for non-blocking fd. This is wrong. After that, read(2) to fd (or write(2) to fd) fails with ENOTCONN if the connection of fd is not completed. The attached patch fixes this problem. -- -- Name: SATOH Fumiyasu (fumiyas @ osstech co jp) -- Business Home: http://www.OSSTech.co.jp/ -- Personal Home: http://www.SFO.jp/blog/ changeset: 12875:43012b126401 branch: fumiyas tag: tip user:SATOH Fumiyasu date:Sat Jul 30 14:17:06 2011 +0900 summary: net_connect_*(): Wait for fd to complete connect(2) when fd is non-blocking diff -r 86c6f58e5756 -r 43012b126401 src/lib/network.c --- a/src/lib/network.c Sat Jul 30 01:21:35 2011 +0900 +++ b/src/lib/network.c Sat Jul 30 14:17:06 2011 +0900 @@ -5,6 +5,7 @@ #include "fd-set-nonblock.h" #include "time-util.h" #include "network.h" +#include "ioloop.h" #include #include @@ -138,6 +139,11 @@ return 0; } +static void net_connect_in_progress(struct ioloop *ioloop) +{ + io_loop_stop(ioloop); +} + #ifdef __FreeBSD__ static int net_connect_ip_full_freebsd(const struct ip_addr *ip, unsigned int port, @@ -207,16 +213,31 @@ /* connect */ sin_set_ip(&so, ip); sin_set_port(&so, port); - ret = connect(fd, &so.sa, SIZEOF_SOCKADDR(so)); + do { + ret = connect(fd, &so.sa, SIZEOF_SOCKADDR(so)); + } while (ret < 0 && errno == EINTR); + + if (ret >= 0) { + return fd; + } #ifndef WIN32 - if (ret < 0 && errno != EINPROGRESS) + if (errno != EINPROGRESS && errno != EALREADY) #else - if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) + if (WSAGetLastError() != WSAEWOULDBLOCK) #endif { -close_keep_errno(fd); + close_keep_errno(fd); return -1; + } else { + struct ioloop *ioloop; + struct io *io; + + ioloop = io_loop_create(); + io = io_add(fd, IO_WRITE, net_connect_in_progress, ioloop); + io_loop_run(ioloop); + io_remove(&io); + io_loop_destroy(&ioloop); } return fd; @@ -286,10 +307,26 @@ net_set_nonblock(fd, TRUE); /* connect */ - ret = connect(fd, &sa.sa, sizeof(sa)); - if (ret < 0 && errno != EINPROGRESS) { -close_keep_errno(fd); + do { + ret = connect(fd, &sa.sa, sizeof(sa)); + } while (ret < 0 && errno == EINTR); + + if (ret >= 0) { + return fd; + } + + if (errno != EINPROGRESS && errno != EALREADY) { + close_keep_errno(fd); return -1; + } else { + struct ioloop *ioloop; + struct io *io; + + ioloop = io_loop_create(); + io = io_add(fd, IO_WRITE, net_connect_in_progress, ioloop); + io_loop_run(ioloop); + io_remove(&io); + io_loop_destroy(&ioloop); } return fd;
Re: [Dovecot] Dovecot 2.0.x + Sendmail 8.14.4 SMTP AUTH not working
Am 30.07.2011 00:58, schrieb Serhiy Kolesnyk: > As I understand Sendmail now can't find Dovecot authentication via > userdb and that's why a client isn't authenticated. Please help. Sendmail has never worked against dovecot's sasl implementation. To use SMTP AUTH with Sendmail you will have to use Cyrus-SASL. Check your previous setup in detail. Alexander
Re: [Dovecot] Dovecot 2.0.x + Sendmail 8.14.4 SMTP AUTH not working
Yep, I didn't pay enough attention to that. I've setup SMTP AUTH via cyrus-SASL-sql. Works fine. I try to do the same with Dovecot's Password verification by SQL server. Which "default_pass_scheme = " I should set? Password is stored as plain text in the db table field. Client (Outlook) authenticates with PLAIN login via POP3s. I guest pass_scheme should be also set to PLAIN ? On Sun, Jul 31, 2011 at 1:21 AM, Alexander Dalloz wrote: > Am 30.07.2011 00:58, schrieb Serhiy Kolesnyk: > >> As I understand Sendmail now can't find Dovecot authentication via >> userdb and that's why a client isn't authenticated. Please help. > > Sendmail has never worked against dovecot's sasl implementation. To use > SMTP AUTH with Sendmail you will have to use Cyrus-SASL. > > Check your previous setup in detail. > > Alexander >
Re: [Dovecot] [PATCH] net_connect_*(): Wait for fd to complete connect(2) when fd is non-blocking
Hi, I've regenerated the patch with 'hg export' instead of 'hg log -p'. (Sorry, I'm a Mercurial newbie.) At Sun, 31 Jul 2011 01:41:22 +0900, SATOH Fumiyasu wrote: > Dovecot ignores EINPROGRESS on connect(2) for non-blocking fd. > This is wrong. After that, read(2) to fd (or write(2) to fd) fails > with ENOTCONN if the connection of fd is not completed. > > The attached patch fixes this problem. -- -- Name: SATOH Fumiyasu (fumiyas @ osstech co jp) -- Business Home: http://www.OSSTech.co.jp/ -- Personal Home: http://www.SFO.jp/blog/ # HG changeset patch # User SATOH Fumiyasu # Date 1312003026 -32400 # Branch fumiyas # Node ID 43012b1264013ce316a23d530d2f0c44c2f53f15 # Parent 86c6f58e57568c9e6b9320365af612cf26d5b278 net_connect_*(): Wait for fd to complete connect(2) when fd is non-blocking mode and connect(2) failes with EINPROGRESS or EALREADY. diff -r 86c6f58e5756 -r 43012b126401 src/lib/network.c --- a/src/lib/network.c Sat Jul 30 01:21:35 2011 +0900 +++ b/src/lib/network.c Sat Jul 30 14:17:06 2011 +0900 @@ -5,6 +5,7 @@ #include "fd-set-nonblock.h" #include "time-util.h" #include "network.h" +#include "ioloop.h" #include #include @@ -138,6 +139,11 @@ return 0; } +static void net_connect_in_progress(struct ioloop *ioloop) +{ + io_loop_stop(ioloop); +} + #ifdef __FreeBSD__ static int net_connect_ip_full_freebsd(const struct ip_addr *ip, unsigned int port, @@ -207,16 +213,31 @@ /* connect */ sin_set_ip(&so, ip); sin_set_port(&so, port); - ret = connect(fd, &so.sa, SIZEOF_SOCKADDR(so)); + do { + ret = connect(fd, &so.sa, SIZEOF_SOCKADDR(so)); + } while (ret < 0 && errno == EINTR); + + if (ret >= 0) { + return fd; + } #ifndef WIN32 - if (ret < 0 && errno != EINPROGRESS) + if (errno != EINPROGRESS && errno != EALREADY) #else - if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) + if (WSAGetLastError() != WSAEWOULDBLOCK) #endif { -close_keep_errno(fd); + close_keep_errno(fd); return -1; + } else { + struct ioloop *ioloop; + struct io *io; + + ioloop = io_loop_create(); + io = io_add(fd, IO_WRITE, net_connect_in_progress, ioloop); + io_loop_run(ioloop); + io_remove(&io); + io_loop_destroy(&ioloop); } return fd; @@ -286,10 +307,26 @@ net_set_nonblock(fd, TRUE); /* connect */ - ret = connect(fd, &sa.sa, sizeof(sa)); - if (ret < 0 && errno != EINPROGRESS) { -close_keep_errno(fd); + do { + ret = connect(fd, &sa.sa, sizeof(sa)); + } while (ret < 0 && errno == EINTR); + + if (ret >= 0) { + return fd; + } + + if (errno != EINPROGRESS && errno != EALREADY) { + close_keep_errno(fd); return -1; + } else { + struct ioloop *ioloop; + struct io *io; + + ioloop = io_loop_create(); + io = io_add(fd, IO_WRITE, net_connect_in_progress, ioloop); + io_loop_run(ioloop); + io_remove(&io); + io_loop_destroy(&ioloop); } return fd;