Menu

#163 ftp::Put success on control timeout

open
ftp (55)
5
2004-03-03
2002-04-25
No

On numerous Tcl versions (up to 8.3) and ftp
library versions (1.2, 2.2, 2.3) we have
experienced false successes for ftp::Put.
Recently, we have noticed that these occur when
ftp::Put encounters the error:
"Timeout of control connection"

If a sequence of files are being sent by ftp::Put,
then subsequent files after the erroneous success
will have their data written to the wrong file name.

E.g.

ftp::Put A is OK

ftp::Put B times out

ftp::Put C sends C's contents to the file B!

As a work-around I set a flag in the
ftp::DisplayMsg procedure within the error
branch. If this flag is set despite ftp::Put
indicating success, then I treat this as a
failed ftp::Put. I then quit the connection
to try again.

Additionally, a couple of times after experiencing
these false-positive results when we have attempted
to quit the connection, we have encountered an
inifinite loop:

bgerror failed to handle background error.
Original error: Unknown state "quit_sent"
Error in bgerror: invalid command name "bgerror"
bgerror failed to handle background error.
Original error: too many nested calls to
Tcl_EvalObj (infinite loop?)
Error in bgerror: too many nested calls to
Tcl_EvalObj (infinite loop?)

(This is using ftp_lib.tcl 2.3 with Tcl 8.3 on
Solaris)

Discussion

  • Andreas Kupries

    Andreas Kupries - 2002-05-14

    Logged In: YES
    user_id=75003

    Can you attach a small script/patch which show how you
    modfied DisplayMsg ? I would basically like to know if you
    check for a specific error message, or just that there was
    an error message. If you know which error message you get,
    well, that would be helpful as well. The ftp sources are a
    bit convoluted and any piece of information you can give me
    will make it easier to find the place where it should error
    out instead of returning a false-positive. Especially as I
    am not the original author of this code.

     
  • Duncan Campbell

    Duncan Campbell - 2002-05-15

    Patch to DisplayMsg and other pieces of info.

     
  • Andreas Kupries

    Andreas Kupries - 2002-10-17

    Logged In: YES
    user_id=75003

    With the error message in your patch I find 'ftp::Timeout'. The
    interesting thing about this procedure is that it sets ftp
    (state.control) to "1". This value seems to become the result
    of the command in execution, and means 'Ok'. Which IMHO
    is not ok. The error value is '0'.

     
  • Duncan Campbell

    Duncan Campbell - 2002-11-08

    Logged In: YES
    user_id=526050

    I've modified 'ftp::Timeout' to set ftp(state.control) to "0" and
    I'm in the process of testing. I've not yet managed to recreate
    the exact scenario to judge the behaviour with this
    modification, but it does appear to be behaving as one would
    hope.

     
  • Duncan Campbell

    Duncan Campbell - 2002-11-22

    Logged In: YES
    user_id=526050

    I have an undesirable result from "set ftp(stat.control) 0"
    in "ftp::Timeout".

    This time we had an unreliable connection that was timing-out
    on the ftp::Get. When trying to close the connection with
    ftp::Close the call to ftp::Timeout from ftp::WaitOrTimeout
    would not return. Instead, it just hung. If I ignored trying to
    close the connection, the connection hung when trying to
    connect next.

    The only reliable solution was to return to "set ftp
    (state.control) 1" in ftp::Timeout, then to close the connection
    with ftp::Close as soon as an error was discovered when
    having run ftp::Get.

     
  • Andreas Kupries

    Andreas Kupries - 2004-03-03
    • assigned_to: andreas_kupries --> gwlester
     
  • Guy Hofkens

    Guy Hofkens - 2007-03-18

    Logged In: YES
    user_id=1625850
    Originator: NO

    I sometimes see the following crash during a ftp::Get :

    can't read "ftp(Start_Time)": no such element in array
    while executing
    "expr {$stop_time - $ftp(Start_Time)}"
    (procedure "ElapsedTime" line 5)
    invoked from within
    "ElapsedTime $s [clock seconds]"
    (procedure "ftp::Get" line 87)

    I think this happens because the proc ftp::WaitOrTimeout (used at the end of ftp::Get) returns 1 on timeout i.s.o. 0. And so ftp::Get tries to calculate the elapsed time in ftp::ElapsedTime, while ftp(Start_Time) is not yet existing, resulting in a crash.
    I have looked at all usage of ftp::WaitOrTimeout, and the return code should be 1 on success, 0 on error. Therefore I suggest to change ftp::Timeout to put ftp(state.control) to 0.

    It solves the crash for me and I think it will solve the related bugs of this thread as well.

    As I am not able to add a patchfile to this comment, I will paste the diff (only a 1 needs to be changed to a 0) :
    --- ftp1.45.tcl 2007-03-16 21:25:07.954228800 +0100
    +++ ftp.tcl 2007-03-18 19:45:10.498745600 +0100
    @@ -121,7 +121,7 @@
    upvar ::ftp::ftp$s ftp

    after cancel $ftp(Wait)
    - set ftp(state.control) 1
    + set ftp(state.control) 0

    DisplayMsg "" "Timeout of control connection after $ftp(Timeout) sec.!" error
    Command $ftp(Command) timeout