On Fri, 12 Feb 2010, Stuart Henderson wrote:

> On 2010/02/11 23:44, Daniel Dickman wrote:
> > ftp(1) will reliably stall for me when doing uploads. I tracked the 
> > problem down to the keep-alive option. Not sure how widespread this issue 
> > is as I'd imagine it depends on what server is on the receiving end. But 
> > here's a sample transcript which gets stuck every time and requires me to 
> > kill the process... the patch below turns off this functionality by 
> > default as it doesn't really work all that well for me for uploads. 
> > (Downloads on this same server work fine though).
> 
> ftp(1) doesn't read until after the transfer finishes, so the
> server has to queue a big batch of "200 NOOP command successful"
> or similar replies and send them in a batch at the end of the
> transfer.
> 
> Every other ftp client that I've investigated which has this
> option reads the replies after each line, which is more friendly
> to the server. I'm not sure if it's implicated in this problem,
> but I think it's fairly likely.
> 
> I've played around with moving getreply() into send_noop_char()
> but something more than this is needed as it freezes after trying
> to read the first response. 
> 
> One problem with disabling keepalive is that some people behind
> crappy nat gateways need it, and there's no easy way to set this
> from the installer (without adding ugly questions, anyway), but
> OTOH pushing them towards using http might be a more sane work-
> around there...
> 
> 

Ok. What about the following defaults:
- interactive mode: disable keep-alive by default.
- auto-fetch mode:  preserve current behaviour (60s between NOOPs by
  default) since I haven't seen any issues with keep-alive when doing
  downloads. This should keep the installer working as before.

At least until the problem can be diagnosed and fixed properly...


Index: ftp.1
===================================================================
RCS file: /usr/cvs/src/usr.bin/ftp/ftp.1,v
retrieving revision 1.79
diff -u -r1.79 ftp.1
--- ftp.1       9 Aug 2009 20:16:39 -0000       1.79
+++ ftp.1       12 Feb 2010 10:46:15 -0000
@@ -174,9 +174,10 @@
 the control connection during a transfer.
 Well-behaved servers queue those commands, and process them after the
 transfer.
-By default,
+By default, this functionality is turned off unless auto-fetching.
+In that case, the default is for
 .Nm
-will send a byte every 60 seconds.
+to send a byte every 60 seconds.
 .It Fl m
 Causes
 .Nm
Index: ftp.c
===================================================================
RCS file: /usr/cvs/src/usr.bin/ftp/ftp.c,v
retrieving revision 1.79
diff -u -r1.79 ftp.c
--- ftp.c       6 Jun 2009 23:14:44 -0000       1.79
+++ ftp.c       12 Feb 2010 09:59:56 -0000
@@ -325,7 +325,7 @@
        return (r);
 }
 
-int keep_alive_timeout = 60;           /* 0 -> no timeout */
+int keep_alive_timeout = -1;           /* 0 -> no timeout */
 
 static int full_noops_sent = 0;
 static time_t last_timestamp = 0;      /* 0 -> no measurement yet */
Index: main.c
===================================================================
RCS file: /usr/cvs/src/usr.bin/ftp/main.c,v
retrieving revision 1.80
diff -u -r1.80 main.c
--- main.c      9 Aug 2009 18:36:11 -0000       1.80
+++ main.c      12 Feb 2010 11:05:59 -0000
@@ -314,6 +314,8 @@
 
        if (argc > 0) {
                if (isurl(argv[0])) {
+                       if (keep_alive_timeout < 0)
+                               keep_alive_timeout = 60;
                        rval = auto_fetch(argc, argv, outfile);
                        if (rval >= 0)          /* -1 == connected and cd-ed */
                                exit(rval);
@@ -321,6 +323,9 @@
 #ifndef SMALL
                        char *xargv[5];
 
+                       if (keep_alive_timeout < 0)
+                               keep_alive_timeout = 0;
+
                        if (setjmp(toplevel))
                                exit(0);
                        (void)signal(SIGINT, (sig_t)intr);
@@ -345,6 +350,9 @@
                }
        }
 #ifndef SMALL
+       if (keep_alive_timeout < 0)
+               keep_alive_timeout = 0;
+
        controlediting();
        top = setjmp(toplevel) == 0;
        if (top) {

Reply via email to