git: 23380f3e6ac9 - main - fetch: Stop setting an alarm

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Mon, 29 Jun 2026 15:52:17 UTC
The branch main has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=23380f3e6ac9334e85489f92f7f20b700ede3368

commit 23380f3e6ac9334e85489f92f7f20b700ede3368
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2026-06-27 15:41:22 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2026-06-29 13:49:19 +0000

    fetch: Stop setting an alarm
    
    Now that fetchTimeout works reliably, setting an alarm is not only no
    longer necessary but counterproductive, as it will trigger even if the
    connection is not actually stalled but merely slow.
    
    While here, improve the wording of the manual page's description of the
    various options for setting a timeout.
    
    MFC after:      1 week
---
 usr.bin/fetch/fetch.1 | 10 ++++++----
 usr.bin/fetch/fetch.c | 33 +++++++++------------------------
 2 files changed, 15 insertions(+), 28 deletions(-)

diff --git a/usr.bin/fetch/fetch.1 b/usr.bin/fetch/fetch.1
index 7238226998fc..17b96d8d459b 100644
--- a/usr.bin/fetch/fetch.1
+++ b/usr.bin/fetch/fetch.1
@@ -28,7 +28,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd October 7, 2023
+.Dd June 27, 2026
 .Dt FETCH 1
 .Os
 .Sh NAME
@@ -283,7 +283,7 @@ ignored and the file is fetched unconditionally.
 .It Fl s , -print-size
 Print the size in bytes of each requested file, without fetching it.
 .It Fl T Ar seconds , Fl -timeout= Ns Ar seconds
-Set timeout value to
+Set the network timeout to
 .Ar seconds .
 Overrides the environment variables
 .Ev FTP_TIMEOUT
@@ -322,9 +322,11 @@ message.
 .Sh ENVIRONMENT
 .Bl -tag -width HTTP_TIMEOUT
 .It Ev FTP_TIMEOUT
-Maximum time, in seconds, to wait before aborting an FTP connection.
+Maximum time, in seconds, to wait before giving up on a stalled FTP
+transfer.
 .It Ev HTTP_TIMEOUT
-Maximum time, in seconds, to wait before aborting an HTTP connection.
+Maximum time, in seconds, to wait before giving up on a stalled HTTP
+transfer.
 .El
 .Pp
 See
diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c
index 5e4b14289ca7..4e2a7596e796 100644
--- a/usr.bin/fetch/fetch.c
+++ b/usr.bin/fetch/fetch.c
@@ -87,7 +87,6 @@ static pid_t	 pgrp;		/*        our process group */
 static long	 w_secs;	/*    -w: retry delay */
 static int	 family = PF_UNSPEC;	/* -[46]: address family to use */
 
-static int	 sigalrm;	/* SIGALRM received */
 static int	 siginfo;	/* SIGINFO received */
 static int	 sigint;	/* SIGINT received */
 
@@ -173,9 +172,6 @@ static void
 sig_handler(int sig)
 {
 	switch (sig) {
-	case SIGALRM:
-		sigalrm = 1;
-		break;
 	case SIGINFO:
 		siginfo = 1;
 		break;
@@ -436,6 +432,7 @@ fetch(char *URL, const char *path, int *is_http)
 	char *tmppath;
 	int r, tries;
 	unsigned timeout;
+	int timedout = 0;
 	char *ptr;
 
 	f = of = NULL;
@@ -519,13 +516,7 @@ fetch(char *URL, const char *path, int *is_http)
 
 	/* just print size */
 	if (s_flag) {
-		if (timeout)
-			alarm(timeout);
 		r = fetchStat(url, &us, flags);
-		if (timeout)
-			alarm(0);
-		if (sigalrm || sigint)
-			goto signal;
 		if (r == -1) {
 			warnx("%s", fetchLastErrString);
 			goto failure;
@@ -574,13 +565,7 @@ again:
 	size_prev = sb.st_size;
 
 	/* start the transfer */
-	if (timeout)
-		alarm(timeout);
 	f = fetchXGet(url, &us, flags);
-	if (timeout)
-		alarm(0);
-	if (sigalrm || sigint)
-		goto signal;
 	if (f == NULL) {
 		if (i_flag && *is_http && fetchLastErrCode == FETCH_OK &&
 		    strcmp(fetchLastErrString, "Not Modified") == 0) {
@@ -748,7 +733,7 @@ again:
 	/* start the counter */
 	stat_start(&xs, path, us.size, count);
 
-	sigalrm = siginfo = sigint = 0;
+	siginfo = sigint = 0;
 
 	/* suck in the data */
 	setvbuf(f, NULL, _IOFBF, B_size);
@@ -785,8 +770,7 @@ again:
 		if (readcnt != 0)
 			break;
 	}
-	if (!sigalrm)
-		sigalrm = ferror(f) && errno == ETIMEDOUT;
+	timedout = ferror(f) && errno == ETIMEDOUT;
 	signal(SIGINFO, SIG_DFL);
 
 	stat_end(&xs);
@@ -811,18 +795,20 @@ again:
 	}
 
 	/* timed out or interrupted? */
-	if (sigalrm)
+	if (timedout) {
 		warnx("transfer timed out");
+		goto failure;
+	}
 	if (sigint) {
 		warnx("transfer interrupted");
 		goto failure;
 	}
 
-	/* timeout / interrupt before connection completley established? */
+	/* timeout / interrupt before connection completely established? */
 	if (f == NULL)
 		goto failure;
 
-	if (!sigalrm) {
+	if (!timedout) {
 		/* check the status of our files */
 		if (ferror(f))
 			warn("%s", URL);
@@ -850,7 +836,7 @@ again:
 	 * If the transfer timed out and we didn't know how much to
 	 * expect, assume the worst (i.e. we didn't get all of it)
 	 */
-	if (sigalrm && us.size == -1) {
+	if (timedout && us.size == -1) {
 		warnx("%s may be truncated", path);
 		goto failure_keep;
 	}
@@ -1126,7 +1112,6 @@ main(int argc, char *argv[])
 	sa.sa_flags = 0;
 	sa.sa_handler = sig_handler;
 	sigemptyset(&sa.sa_mask);
-	sigaction(SIGALRM, &sa, NULL);
 	sa.sa_flags = SA_RESETHAND;
 	sigaction(SIGINT, &sa, NULL);
 	fetchRestartCalls = 0;