Hi all, > > There was an irritating glitch, which I have also seen mentioned a few > > times > > online. It is that if you have mutt open, pack up your laptop, and go > > somewhere else, mutt is completely unresponsive and needs to be killed. I > > tracked down what was causing this and to my satisfaction my fix works. > > > > Would you be interested in this patch? And, if the intended behaviour is > > that it should hang like this, then perhaps my fix could be implemented as > > a > > config variable. (It’s basically just a simple timeout + retry mechanism in > > the socket_connect function). > > Please go ahead and post your patch, either to this list, or perhaps to > a ticket. It looks like http://dev.mutt.org/trac/ticket/3369 or > http://dev.mutt.org/trac/ticket/3491 might be related. > > Most of the committers are quite busy right now, so it may take a while > to get a response.
Attached is my patch for the hanging socket problem. I hope this fixes 3369 and 3491, which indeed sound very similar to the problem I reported. All comments welcome. I used hg export against the tip of the default branch to produce the diff; please let me know if you would rather have it another way. > > > Also, you’ve probably talked about this many times before, but is there a > > reason not to implement a config option to call a command when there is new > > mail? > > Yoshiki Vazquez Baeza posted a patch for this a couple months ago, and > David Champion is incorporating it into a related patch set. > Yours, Allen
# HG changeset patch # User misterfish <al...@netherrealm.net> # Date 1430247531 -7200 # Tue Apr 28 20:58:51 2015 +0200 # Node ID 65d3b99e229cefaec62e8205fec116a7c00fce72 # Parent 755a18da99bc0a57bd6e462f5971eba7b9f61604 Fix bug where mutt hangs indefinitely when, for example, you pack up your laptop and open it again somewhere else. Introduce a timeout on sockets ("socket_timeout" in muttrc, default 5 seconds) and a fixed number of retries for GNUTLS ("ssl_socket_num_tries" in muttrc, default is 2). Hopefully fixes #3369 and #3491. diff -r 755a18da99bc -r 65d3b99e229c globals.h --- a/globals.h Sat Apr 25 19:00:13 2015 -0700 +++ b/globals.h Tue Apr 28 20:58:51 2015 +0200 @@ -193,6 +193,8 @@ WHERE unsigned short Counter INITVAL (0); WHERE short ConnectTimeout; +WHERE short SocketTimeout; +WHERE short GNUTLSSocketNumTries; WHERE short HistSize; WHERE short MenuContext; WHERE short PagerContext; diff -r 755a18da99bc -r 65d3b99e229c init.h --- a/init.h Sat Apr 25 19:00:13 2015 -0700 +++ b/init.h Tue Apr 28 20:58:51 2015 +0200 @@ -2888,6 +2888,14 @@ ** variable. */ #endif /* USE_SMTP */ + { "socket_timeout", DT_NUM, R_NONE, UL &SocketTimeout, 5 }, + /* + ** .pp + ** Close inactive sockets after this many seconds. When set to zero or a + ** negative value, mutt will wait indefinitely on sockets, but be warned + ** that this can cause mutt to hang. If using GNUTLS, you must also set + ** $$ssl_socket_num_tries to a non-zero value. + */ { "sort", DT_SORT, R_INDEX|R_RESORT, UL &Sort, SORT_DATE }, /* ** .pp @@ -3025,6 +3033,15 @@ ** for use in any Diffie-Hellman key exchange. A value of 0 will use ** the default from the GNUTLS library. */ + { "ssl_socket_num_tries", DT_NUM, R_NONE, UL &GNUTLSSocketNumTries, 2 }, + /* + ** .pp + ** When using GNUTLS, this can be used in conjunction with + ** $$socket_timeout to cause the mailbox to close after the socket has + ** timed out this many times. If set to zero or a negative number, the + ** socket will wait for data indefinitely, but be aware that this can + ** cause mutt to hang. + */ # endif /* USE_SSL_GNUTLS */ { "ssl_starttls", DT_QUAD, R_NONE, OPT_SSLSTARTTLS, M_YES }, /* diff -r 755a18da99bc -r 65d3b99e229c mutt_socket.c --- a/mutt_socket.c Sat Apr 25 19:00:13 2015 -0700 +++ b/mutt_socket.c Tue Apr 28 20:58:51 2015 +0200 @@ -344,6 +344,7 @@ { int sa_size; int save_errno; + struct timeval socket_timeout_tv = {0}; if (sa->sa_family == AF_INET) sa_size = sizeof (struct sockaddr_in); @@ -364,6 +365,28 @@ save_errno = 0; + /* Set a timeout on the socket. + * Can be set to 0 for no timeout, but then, mutt can hang forever waiting + * for data. + * For OpenSSL this is enough to avoid hanging, but with GNUTLS, + * ssl_socket_num_tries must also be set in the config. + */ + + if (SocketTimeout > 0) { + socket_timeout_tv.tv_sec = SocketTimeout; + if (setsockopt(fd, + SOL_SOCKET, /* protocol level */ + SO_RCVTIMEO, /* optname */ + &socket_timeout_tv, /* const void *optval */ + sizeof(struct timeval) + )) + { + mutt_perror(_("Couldn't set socket_timeout")); + mutt_sleep(3); + return -1; + } + } + if (connect (fd, sa, sa_size) < 0) { save_errno = errno; diff -r 755a18da99bc -r 65d3b99e229c mutt_ssl_gnutls.c --- a/mutt_ssl_gnutls.c Sat Apr 25 19:00:13 2015 -0700 +++ b/mutt_ssl_gnutls.c Tue Apr 28 20:58:51 2015 +0200 @@ -131,6 +131,7 @@ { tlssockdata *data = conn->sockdata; int ret; + int try = 0; if (!data) { @@ -139,7 +140,20 @@ return -1; } + /* When the socket times out, ret is GNUTLS_E_AGAIN. + * When socket_timeout (SocketTimeout) is 0, the socket is set to + * blocking, and this will hang forever on gnutls_record_recv. + * If the timeout is set, but ssl_socket_num_tries (GNUTLSSocketNumTries) + * is equal to zero or a negative value, this will become an infinite loop + * and mutt will hang. + */ + do { + if (GNUTLSSocketNumTries > 0 && ++try > GNUTLSSocketNumTries) { + mutt_error(_("Timed out reading from socket, closing mailbox.")); + mutt_sleep(2); + return -1; + } ret = gnutls_record_recv (data->state, buf, len); if (ret < 0 && gnutls_error_is_fatal(ret) == 1) {
signature.asc
Description: Digital signature