Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Aug 2002 11:53:53 -0400 (EDT)
From:      Keith White <Keith.White@site.uottawa.ca>
To:        Ian Dowse <iedowse@FreeBSD.org>
Cc:        kwhite@uottawa.ca, <freebsd-bugs@FreeBSD.org>, <bug-followup@FreeBSD.org>
Subject:   Re: bin/20042: "rsh -t" doesn't timeout if rcmd(3) never returns [patch included]
Message-ID:  <Pine.GSO.4.44.0208131142590.29347-100000@siteao.site.uottawa.ca>
In-Reply-To: <200208092350.g79No5oZ096260@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 9 Aug 2002, Ian Dowse wrote:

> Synopsis: "rsh -t" doesn't timeout if rcmd(3) never returns [patch included]
>
> State-Changed-From-To: open->feedback
> State-Changed-By: iedowse
> State-Changed-When: Fri Aug 9 16:44:37 PDT 2002
> State-Changed-Why:
>
> It isn't safe to call errx() from a signal handler - would you
> like to suggest a better patch that uses only functions that are
> documented in sigaction(2) as being safe to call? You can also
> remove the #ifdef's from around the new code.
>
> http://www.freebsd.org/cgi/query-pr.cgi?pr=20042

My initial bug report didn't include an easy way to demonstrate the
problem.  This will.

server# kill -STOP `cat /var/run/inetd.pid`

client$ rsh -t 5 server who
        ...wait, rsh doesn't return after 5 seconds...

after patching rsh
client$ rsh -t 5 server who
        timeout reached before connection completed.

server# kill -CONT `cat /var/run/inetd.pid`

The following patch should fulfill the criteria:

---cut here---
--- rsh.c.orig	Sun Mar  4 04:01:45 2001
+++ rsh.c	Tue Aug 13 09:57:06 2002
@@ -89,6 +89,7 @@

 char   *copyargs __P((char **));
 void	sendsig __P((int));
+void	connect_timeout __P((int));
 void	talk __P((int, long, pid_t, int, int));
 void	usage __P((void));

@@ -283,8 +284,22 @@
 			      &rfd2, family);
 	}
 #else
+
+/*
+ * it is possible that the rcmd() will never return -- perhaps because the
+ * remote machine is hung -- so add an alarm just in case
+ */
+
+	if (timeout) {
+		signal(SIGALRM, connect_timeout);
+		alarm(timeout);
+	}
 	rem = rcmd_af(&host, sp->s_port, pw->pw_name, user, args, &rfd2,
 		      family);
+	if (timeout) {
+		signal(SIGALRM, SIG_DFL);
+		alarm(0);
+	}
 #endif

 	if (rem < 0)
@@ -446,6 +461,19 @@
 				(void)write(1, buf, cc);
 		}
 	} while (FD_ISSET(rfd2, &readfrom) || FD_ISSET(rem, &readfrom));
+}
+
+void
+connect_timeout(sig)
+	int sig;
+{
+	char message[] = "timeout reached before connection completed.\n";
+/*
+ * why not use errx()? -- we're in a signal handler so must restrict ourselves
+ * to those functions listed in sigaction(2)
+ */
+	write(STDERR_FILENO, message, sizeof(message)-1);
+	_exit(1);
 }

 void
---cut here---

...keith
-- 
Keith White, EITI/SITE, University of Ottawa
kwhite@site.uottawa.ca [+1 613 562 5800 x6681] FAX [+1 613 562 5664]


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.44.0208131142590.29347-100000>