[tin-dev] [PATCH] infinite loop during connection setup

Dennis Preiser dennis at d--p.de
Sun Oct 18 15:49:58 CEST 2015


Recently I encountered a bug when using tin with stunnel. When stunnel
is running but the network is down (in my case WIFI was switched off)
tin goes right after startup into an infinite loop:

get_server() -> reconnect() -> nntp_open() -> server_init() ->
get_respcode() -> get_only_respcode() -> tin_fgets() -> tin_read() ->
get_server() -> reconnect() …

Here is a basic setup to reproduce:

stunnel.conf:
| [nntp]
| client      = yes
| accept      = 127.0.0.1:1119
| connect     = news.example.com:563

newsrctable:
| 127.0.0.1	~/.newsrcs	alias

.newsauth
| 127.0.0.1	pass	user

Start stunnel, make sure network is down and start tin as follows:
tin -p 1119 -A -g alias

If tin was build without --enable-debug, it takes about 10 seconds until
a Segmentation fault.

Attached a patch with a possible fix.

Dennis
-------------- next part --------------
diff -urp tin-2.3.1_r9/src/nntplib.c tin-2.3.1_r10/src/nntplib.c
--- tin-2.3.1_r9/src/nntplib.c	2014-12-24 09:41:24.000000000 +0100
+++ tin-2.3.1_r10/src/nntplib.c	2015-10-18 14:56:29.000000000 +0200
@@ -821,17 +821,20 @@ reconnect(
 	signal_context = cReconnect;
 
 	/*
-	 * Exit tin if the user says no to reconnect. The exit code stops tin from trying
-	 * to disconnect again - the connection is already dead
+	 * Exit tin if there are no more tries or if the user says no to reconnect.
+	 * The exit code stops tin from trying to disconnect again - the connection
+	 * is already dead
 	 */
-	if (!tinrc.auto_reconnect && prompt_yn(_(txt_reconnect_to_news_server), TRUE) != 1) {
+	if (!retry || (!tinrc.auto_reconnect && prompt_yn(_(txt_reconnect_to_news_server), TRUE) != 1)) {
 		if (!strncmp("POST", last_put, 4)) {
 			unlink(backup_article_name(article_name));
 			rename_file(article_name, dead_article);
 			if (tinrc.keep_dead_articles)
 				append_file(dead_article, dead_articles);
 		}
-		tin_done(NNTP_ERROR_EXIT);		/* user said no to reconnect */
+		if (!retry)
+			error_message(2, _("NNTP connection error. Exiting..."));
+		tin_done(NNTP_ERROR_EXIT);		/* user said no to reconnect or no more retries */
 	}
 
 	/*
@@ -861,17 +864,7 @@ reconnect(
 		DEBUG_IO((stderr, _("Resend last command (%s)\n"), buf));
 		put_server(buf);
 		did_reconnect = TRUE;
-		return 0;
-	}
-
-	if (--retry == 0) {					/* No more tries? */
-		if (!strncmp("POST", buf, 4)) {
-			unlink(backup_article_name(article_name));
-			rename_file(article_name, dead_article);
-			if (tinrc.keep_dead_articles)
-				append_file(dead_article, dead_articles);
-		}
-		tin_done(NNTP_ERROR_EXIT);
+		retry = 0;
 	}
 
 	return retry;
@@ -896,7 +889,7 @@ get_server(
 	char *string,
 	int size)
 {
-	int retry = NNTP_TRY_RECONNECT;
+	static int retry_cnt = NNTP_TRY_RECONNECT;
 
 	reconnected_in_last_get_server = FALSE;
 	errno = 0;
@@ -947,7 +940,7 @@ get_server(
 				strcpy(last_put, "MODE READER");
 				nntp_caps.type = BROKEN;
 			}
-			retry = reconnect(retry);		/* Will abort when out of tries */
+			retry_cnt = reconnect(retry_cnt--);		/* Will abort when out of tries */
 			reconnected_in_last_get_server = TRUE;
 		} else {
 			/*
@@ -962,6 +955,7 @@ get_server(
 #	if defined(HAVE_ALARM) && defined(SIGALRM)
 	alarm(0);
 #	endif /* HAVE_ALARM && SIGALRM */
+	retry_cnt = NNTP_TRY_RECONNECT;
 	return string;
 }
 


More information about the tin-dev mailing list