Adam Thompson <[email protected]> wrote:

> Summary:  I open cua0 with cu(1), quit cu(1), try to re-open with
> cu(1) but now it immediately fails with EBUSY.  *Usually* doesn't
> happen with USB-to-serial (cuaU[0-9]) but have still seen it once or
> twice.
> 
> I've seen this behaviour on OpenBSD 6.4, OpenBSD 6.5, and FreeBSD
> 11.2, and on 3 radically different systems (hardware-wise) so I don't
> think it's a version-specific or even hardware-specific bug, more
> likely something I'm failing to understand.
> 
> I'm using OpenBSD as a remote serial console server for up to 3
> switches at a time (OOB access to a few switches in my lab).  This
> works, mostly... but occasionally, a serial port, almost always the
> onboard hardware cua0/tty0 port, somehow wedges and requires me to
> reboot the OBSD system to regain access to it.  The symptom is that
> when attempting to open(2) the device, I get EBUSY... for no obvious
> reason.  fuser(1) shows no other processes having a filehandle on
> /dev/cua00.
> 
> I don't understand why this happens inconsistently - about ~75% of the
> time on /dev/cua00, but only ~10% of the time on /dev/cuaU[0-1].  Of
> the ~75% of the time it happens on /dev/cua00, about 1/3 of those
> times, if I wait a minute or ten, I can then re-open the device (again
> using cu(1)), and 2/3 of those times it persists until a reboot.
> 
> On the USB devices, I can - with 100% success - eliminate the problem
> by walking over, unplugging the serial adapter, and re-inserting it.
> 
> I haven't tried using e.g. screen(1) from ports, I've only tested
> using cu(1) in base so far.  I can try something else if there's a
> reason to... on the OpenBSD box anyway, it'll be a bit harder on the
> FreeBSD appliance.
> 
> As I said, I've even seen this on FreeBSD, so I expect I just need
> someone to provide an explanation of what nuance of tty(4) usage I'm
> missing.


All these drivers have a "close" function which is called upon last
close().  From dev/ic/com.c:

int
comclose(dev_t dev, int flag, int mode, struct proc *p)
{
        int unit = DEVUNIT(dev);
        struct com_softc *sc = com_cd.cd_devs[unit];
        struct tty *tp = sc->sc_tty;
        int s;

#ifdef COM_CONSOLE
        /* XXX This is for cons.c. */
        if (!ISSET(tp->t_state, TS_ISOPEN))
                return 0;
#endif

        if(sc->sc_swflags & COM_SW_DEAD)
                return 0;

        (*linesw[tp->t_line].l_close)(tp, flag, p);
        s = spltty();
        if (ISSET(tp->t_state, TS_WOPEN)) {
                /* tty device is waiting for carrier; drop dtr then re-raise */
                CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
                com_write_reg(sc, com_mcr, sc->sc_mcr);
                timeout_add_sec(&sc->sc_dtr_tmo, 2);
                ...

You are observing the forcing-down of DTR and RTS for a long enough
period that the other side of the link notices the event.

Therefore it is not suprising you are finding this behaviour very
similar in many drivers and operating systems.

Reply via email to