The "::libcisco::session open" command may leave
expect channels open when it failed to open a libcisco
session due to something the script didn't expect (e.g.
the router wasn't a Cisco router, or a Cisco router's login
banner matched the regular expression for a Catalyst
user-mode prompt). As libcisco doesn't seem to be
designed to handle multiple concurrent sessions (I
believe that I have read something to that effect
somewhere), a timeout of the telnet connection that is
detected by a previously spawned session that was
neither properly opened nor properly closed tends to
mess up libcisco's ability to handle a more recent session
connected to another router that is returning perfectly
good responses.
On top of it, "::libcisco::session open" does not return
the channel/spawn/session ID of the failed session, so
you wouldn't know what expect channel to close from
outside libcisco.
A relatively simple workaround is to have the
SpawnTelnet() function set an additional member
variable of the "state" structure. In the version of the
script uploaded as part of this bug report, I have called
this member variable last_attempted_new_spawn_id. In
this way, a script using the libcisco package can run
some clean-up code of its own when it detects
that "::libcisco::session open" did not succeed, e.g. as
follows:
catch \
{
close -i $::libcisco::state
(last_attempted_new_spawn_id);
wait -i $::libcisco::state
(last_attempted_new_spawn_id);
}
Of course, it would be desirable for "::libcisco::session
open" itself to always close the expect channel for any
failed connection. My suggested fix still does not
address at least one minor issue (if you used the -logfile
option in the "::libcisco::session open" statement, and
you open another session with another log file after a
failed session, the session log ends up in duplicate in the
log files of both the previous and the current session).
If you use libcisco 1.3 as it is, the workaround would
probably be to avoid writing a single TCL script
containing both a loop over several routers and the
actual use of the libcisco package; instead, it may be
better to design a specialized expect script to handle
just a single router, and code the loop in a separate
script (which may or may not be in TCL) that would
launch one instance of the expect script for each single
router.
libkernel.tcl