>Synopsis: process hangs in "ttyout" state on /dev/cuaXX
>Category: kernel
>Environment:
System : OpenBSD 4.9
Details : OpenBSD 4.9 (GENERIC) #45: Wed Mar 16 07:21:38 YEKT 2011
[email protected]:/usr/src/sys/arch/i386/compile/GENERIC
Architecture: OpenBSD.i386
Machine : i386
>Description:
It's related to this
http://marc.info/?l=openbsd-tech&m=129982036820357&w=2
I found the problem with the /dev/cuaXX device.
This device voluntary set the TS_CARR_ON flag, so if the program tune
it's terminal settings so that the CSTRCTS flag is set then it can be
a problem.
The program shows the principle:
>How-To-Repeat:
#include <err.h>
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
int
main(int argc, char **argv)
{
int dev;
struct termios tio;
unsigned char byte[1] = {0x0};
if ((dev = open("/dev/cua02", O_RDWR, 0)) == -1)
err(1, "open() failed");
if (tcgetattr(dev, &tio) == -1)
err(1, "tcgetattr() failed");
tio.c_cflag = CS8|CREAD|CRTSCTS;
if (tcsetattr(dev, TCSANOW, &tio) == -1)
err(1, "tcsetattr() failed");
printf("write\n");
if (write(dev, byte, sizeof(byte)) == -1)
err(1, "write() failed");
printf("read\n");
if (read(dev, byte, sizeof(byte)) == -1)
err(1, "read() failed");
close(dev);
}
The program write something to the /dev/cua02 device, but nothing
connected to that COM port.
This process can't be kill -KILL'ed, and port stays busy.
(but if I remove CRTSCTS flag or "read()" branch the process not hangs)
$ gcc ct.c -o ct
$ ./ct
write
read
^C
$ ps axl
...
1000 27788 10863 15 4 0 464 568 ttyout SE+ p0 0:00.01 (ct)
ddb> trace /p 0x6c8c
sleep_finish(c0,d08b9e79,d992ebc8,d992eba4,d992eba4) at sleep_finish+0x99
sleep_finish(d992eba4,1,11a,d09c05f6,80) at sleep_finish+0x99
tsleep(d15a9e48,11a,d09c05f6,0,d15a9e00) at tsleep+0x9d
ttysleep(d15a9e00,d15a9e48,11a,d09c05f6,0) at ttysleep+0x36
ttywait(d15a9e00,7fffffff,d992ec5c,d03e3450,d1577000) at ttywait+0x8e
ttywflush(d15a9e00,d13a7188,d992ec6c,d02cccce,d15a9e00) at ttywflush+0x17
ttylclose(d15a9e00,3,d5b2000c,d5b2000c,d992ec94) at ttylclose+0x2b
comclose(882,3,2000,d5b2000c,d992ec94) at comclose+0x6e
spec_close(d992ecf8,20000,d992ecdc,d041772a,d992eccc,20042,0,d5b99038) at spec_
close+0x102
ufsspec_close(d992ecf8,20042,d5b2000c,d5b99038,20042) at ufsspec_close+0xdc
VOP_CLOSE(d5b99038,3,d5d45280,d5b2000c,d5b2000c) at VOP_CLOSE+0x30
vn_close(d5b99038,3,d5d45280,d5b2000c,d5b2000c,3f000,0,d041d39a,d5d0e1e0,20002,
3,0,d5b99038,d992eea0,d992ed9c,d5b99038) at vn_close+0x4f
vn_closefile(d5b48c60,d5b2000c,0,d0576245,d140a240) at vn_closefile+0x80
closef(d5b48c60,d5b2000c,d992edfc,2,d5d3a908) at closef+0x5d
fdfree(d5b2000c,1,d5b2000c,d5d45280,d5d3a900) at fdfree+0x52
exit1(d5b2000c,2,1,d5d45280,d5b2000c) at exit1+0x14b
sigexit(d5b2000c,2,8,d5ceb804,0) at sigexit+0x3f
postsig(2,d992ef64,d992ef84,d992efa8,d5b2000c) at postsig+0x255
syscall() at syscall+0x25e
--- syscall (number -809725760) ---
0x2:
It shows that the kernel tries to flush "unsended" byte(s) and, since
the TS_CARR_ON flag is on, the tty code relies on carrier and wait
(forever) for something.
/usr/src/sys/kern/tty.c:
ttywait(struct tty *tp)
{
while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
(ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) &&
tp->t_oproc) {
(*tp->t_oproc)(tp);
if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
(ISSET(tp->t_state, TS_CARR_ON) ||
ISSET(tp->t_cflag, CLOCAL))
&& tp->t_oproc) {
SET(tp->t_state, TS_ASLEEP);
error = ttysleep(tp, &tp->t_outq, TTOPRI |
PCATCH, ttyout, 0);
...
>Fix:
It tried to resolve this in different ways (see the related topic). In
the end I make this patch:
--- /usr/origsrc/sys/dev/ic/com.c Mon Oct 11 22:19:28 2010
+++ /usr/src/sys/dev/ic/com.c Wed Mar 16 06:18:34 2011
@@ -489,6 +489,8 @@
if(sc->sc_swflags & COM_SW_DEAD)
return 0;
+ if (DEVCUA(dev))
+ SET(tp->t_state, TS_DEVCUA_CLOSING);
(*linesw[tp->t_line].l_close)(tp, flag, p);
s = spltty();
if (ISSET(tp->t_state, TS_WOPEN)) {
@@ -987,6 +989,8 @@
int s;
s = spltty();
+ if (ISSET(tp->t_state, TS_DEVCUA_CLOSING))
+ tp->t_outq.c_cc = 0;
if (ISSET(tp->t_state, TS_BUSY))
goto out;
if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0)
--- /usr/origsrc/sys/sys/tty.h Mon Oct 11 22:20:38 2010
+++ /usr/src/sys/sys/tty.h Wed Mar 16 06:08:19 2011
@@ -201,6 +201,8 @@
#define TS_TSTAMPCTSSET 0x40000 /* update timestamp on CTS set
*/
#define TS_TSTAMPCTSCLR 0x80000 /* update timestamp on CTS clr
*/
+#define TS_DEVCUA_CLOSING 0x100000 /* close(/dev/cuaXX) in
progress. */
+
/* Character type information. */
#define ORDINARY 0
#define CONTROL 1
But I'm still not sure that it is right way.
dmesg:
OpenBSD 4.9 (GENERIC) #45: Wed Mar 16 07:21:38 YEKT 2011
[email protected]:/usr/src/sys/arch/i386/compile/GENERIC
cpu0: Vortex86 SoC (586-class) 1.01 GHz
cpu0: FPU,TSC,CX8
real mem = 536440832 (511MB)
avail mem = 517533696 (493MB)
mainbus0 at root
bios0 at mainbus0: AT/286+ BIOS, date 06/29/10, BIOS32 rev. 0 @ 0xf0010
apm0 at bios0: Power Management spec V1.2
apm0: AC on, battery charge unknown
pcibios0 at bios0: rev 3.0 @ 0xf0000/0x10000
pcibios0: PCI IRQ Routing Table rev 1.0 @ 0xf34d0/240 (13 entries)
pcibios0: no compatible PCI ICU found: ICU vendor 0x17f3 product 0x6036
pcibios0: Warning, unable to fix up PCI interrupt routing
pcibios0: PCI bus #0 is the last bus
bios0: ROM list: 0xc0000/0x8000 0xe9400/0x200!
cpu0 at mainbus0: (uniprocessor)
pci0 at mainbus0 bus 0: configuration mode 1 (bios)
pchb0 at pci0 dev 0 function 0 "RDC R6021 Host" rev 0x02
pcib0 at pci0 dev 7 function 0 vendor "RDC", unknown product 0x6036 rev 0x00
vte0 at pci0 dev 8 function 0 "RDC R6040 Ethernet" rev 0x00: irq 7,
address 00:1b:eb:66:23:8f
rdcphy0 at vte0 phy 1: R6040 10/100 PHY, rev. 1
ohci0 at pci0 dev 10 function 0 "RDC R6060 USB" rev 0x12: irq 3,
version 1.0, legacy support
ehci0 at pci0 dev 10 function 1 "RDC R6061 USB" rev 0x03: irq 3
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 "RDC EHCI root hub" rev 2.00/1.00 addr 1
ohci1 at pci0 dev 11 function 0 "RDC R6060 USB" rev 0x12: irq 3,
version 1.0, legacy support
ehci1 at pci0 dev 11 function 1 "RDC R6061 USB" rev 0x03: irq 3
usb1 at ehci1: USB revision 2.0
uhub1 at usb1 "RDC EHCI root hub" rev 2.00/1.00 addr 1
pciide0 at pci0 dev 12 function 0 "RDC R1011 IDE" rev 0x01: DMA,
(partial support), channel 0 configured to compatibility, channel 1
configured to compatibility
wd0 at pciide0 channel 0 drive 0: <SD04G RDC SD-IDE HOST CONTROLLER>
wd0: 1-sector PIO, LBA, 3796MB, 7774208 sectors
pciide0: channel 1 ignored (not responding; disabled or no drives?)
pciide0:0:0: using DMA data transfers
vga1 at pci0 dev 13 function 0 vendor "RDC", unknown product 0x2010 rev 0x00
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
azalia0 at pci0 dev 14 function 0 vendor "RDC", unknown product 0x3010
rev 0x01: irq 9
azalia0: No codecs found
azalia0: initialization failure, detaching
isa0 at pcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com0: console
com2 at isa0 port 0x3e8/8 irq 5: ns16550a, 16 byte fifo
com2: probed fifo depth: 0 bytes
pckbc0 at isa0 port 0x60/5
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16
usb2 at ohci0: USB revision 1.0
uhub2 at usb2 "RDC OHCI root hub" rev 1.00/1.00 addr 1
usb3 at ohci1: USB revision 1.0
uhub3 at usb3 "RDC OHCI root hub" rev 1.00/1.00 addr 1
biomask ff4d netmask ffcd ttymask ffff
vscsi0 at root
scsibus0 at vscsi0: 256 targets
softraid0 at root
root on wd0a swap on wd0b dump on wd0b
WARNING: / was not properly unmounted
usbdevs:
Controller /dev/usb0:
addr 1: high speed, self powered, config 1, EHCI root hub(0x0000),
RDC(0x17f3), rev 1.00
port 1 powered
port 2 powered
Controller /dev/usb1:
addr 1: high speed, self powered, config 1, EHCI root hub(0x0000),
RDC(0x17f3), rev 1.00
port 1 powered
port 2 powered
Controller /dev/usb2:
addr 1: full speed, self powered, config 1, OHCI root hub(0x0000),
RDC(0x17f3), rev 1.00
port 1 powered
port 2 powered
Controller /dev/usb3:
addr 1: full speed, self powered, config 1, OHCI root hub(0x0000),
RDC(0x17f3), rev 1.00
port 1 powered
port 2 powered