So -- in devip on Inferno hosted we have this bit of code: (connectctlmsg)
if(c->state != Idle)
error(Econinuse);
c->state = Connecting;
...
if(waserror()){
qlock(&c->l);
c->state = Connected; /* sic */
nexterror();
}
/* p = x->connect(c, cb->f, cb->nf); */
so_connect(c->sfd, ip6w(c->raddr), c->rport);
qlock(&c->l);
poperror();
In native inferno (and Plan 9) devip we have this bit of code:
if(c->state != 0)
error(Econinuse);
c->state = Connecting;
...
if(waserror()){
qlock(c);
nexterror();
}
sleep(&c->cr, connected, c);
qlock(c);
poperror();
------------------
The result being if the connect fails, the state remains Connecting,
and subsequent writes of 'connect' commands fail because Econinuse.
In Plan 9/Inferno, this doesn't really matter much because if dial(2)
fails we close the fd to the ctl file.
Now in the Libra library OS stuff that I've been working on, we are
using a slight different (more socket-ish) semantic. There's nothing
in the devip man pages that say that I can't issue new commands to the
ctl file after a failed command.
So, bug or feature? At the very least it would seem a good idea to
set c->state to Hungup (and also change the c->state != 0 to a
c->state != Idle). I have no idea why we set c->state to Connected in
Inferno hosted -- that just seems completely bonkers.
-eric