bug-ncurses
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Return value of write() is not properly evaluated


From: Stian Skjelstad
Subject: Return value of write() is not properly evaluated
Date: Tue, 30 Dec 2014 15:26:57 +0100

Hello

I am the maintainer of Open Cubic Player, and the last couple of days I have done a couple of tests, using ncurses on lubuntu.

I stumbled across some graphical issues, and it appeared visible in several different terminal emulators when running on higher resolutions. After some experimentation I discovered that the problem was not visible if streaming stdout via tools like tee: eg
ocp-curses | tee                  <- no UI noise
ocp-curses                         <- UI noise every now and then

Later I did some more testing with strace, and I discovered one point that I think is the key issue

write(1, "\33[H\33[30m\37m\3..........", 8025) = 4096
--- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---
ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0x1)   = 0
ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0x3)   = 0
ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0x20)  = 0
ioctl(4, SNDRV_PCM_IOCTL_HWSYNC, 0x20)  = 0
getitimer(ITIMER_REAL, {it_interval={0, 14320}, it_value={0, 9190}}) = 0
rt_sigreturn()                          = 4096
rt_sigaction(SIGTSTP, {0x7f2f4f97a0b0, [], SA_RESTORER|SA_RESTART, 0x7f2f50e17da0}, NULL, 8) = 0
select(1, [0], NULL, NULL, {0, 0})      = 0 (Timeout)


The usage of setitimer() can cause write() to return before a complete write has occurred. If piped via software like tee, the receiver will swallow bigger chunks of the buffer, making it more likely that a full buffer is sent before write() returns.


But I try to follow the code-path in ncurses, and it is not the most easy code to read, especially when looking at the stack-trace when the library is compiled with optimizations enabled, and lots of macro-magic in the ncurses sources.

I found that the current write-out happens via

#0  write () at ../sysdeps/unix/syscall-template.S:81
#1  0x00007ffff61828a6 in _nc_flush () at /build/buildd/ncurses-5.9+20140712/ncurses/tinfo/lib_tputs.c:130
#2  0x00007ffff63b20f2 in doupdate () at /build/buildd/ncurses-5.9+20140712/ncurses/tty/tty_update.c:999
#3  0x00007ffff63a76d9 in wrefresh (address@hidden) at /build/buildd/ncurses-5.9+20140712/ncurses/base/lib_refresh.c:65
#4  0x00007ffff63a13b9 in recur_wrefresh (address@hidden) at /build/buildd/ncurses-5.9+20140712/ncurses/base/lib_getch.c:384
#5  0x00007ffff63a1532 in _nc_wgetch (address@hidden, address@hidden, use_meta=1) at /build/buildd/ncurses-5.9+20140712/ncurses/base/lib_getch.c:491
#6  0x00007ffff63a2255 in wgetch (win=0x670d40) at /build/buildd/ncurses-5.9+20140712/ncurses/base/lib_getch.c:670
#7  0x00007ffff65ca923 in ekbhit () at poutput-curses.c:288
#8  0x00007ffff1ae4012 in plmpDrawScreen () at cpiface.c:708
#9  plmpCallBack () at cpiface.c:824
#10 0x00007ffff49b382f in _fsMain (argc=1, argv=0x668640) at pfsmain.c:309
#11 0x00007ffff7607271 in init_modules (address@hidden, address@hidden) at pmain.c:394
#12 0x00007ffff7608006 in _bootup (argc=2, argv=0x7fffffffde68) at pmain.c:450
#13 0x0000000000401375 in runocp (argv=0x7fffffffde68, argc=2, handle=<optimized out>) at kickload.c:582

Dump of assembler code for function _nc_flush:
   0x00007ffff6182850 <+0>: push   %r13
   0x00007ffff6182852 <+2>: push   %r12
   0x00007ffff6182854 <+4>: push   %rbp
   0x00007ffff6182855 <+5>: push   %rbx
   0x00007ffff6182856 <+6>: sub    $0x8,%rsp
   0x00007ffff618285a <+10>: mov    0x2126b7(%rip),%rax        # 0x7ffff6394f18
   0x00007ffff6182861 <+17>: mov    (%rax),%rbx
   0x00007ffff6182864 <+20>: test   %rbx,%rbx
   0x00007ffff6182867 <+23>: je     0x7ffff6182879 <_nc_flush+41>
   0x00007ffff6182869 <+25>: mov    0x4(%rbx),%ebp
   0x00007ffff618286c <+28>: test   %ebp,%ebp
   0x00007ffff618286e <+30>: js     0x7ffff6182879 <_nc_flush+41>
   0x00007ffff6182870 <+32>: mov    0x20(%rbx),%r12
   0x00007ffff6182874 <+36>: test   %r12,%r12
   0x00007ffff6182877 <+39>: jne    0x7ffff6182888 <_nc_flush+56>
   0x00007ffff6182879 <+41>: add    $0x8,%rsp
   0x00007ffff618287d <+45>: pop    %rbx
   0x00007ffff618287e <+46>: pop    %rbp
   0x00007ffff618287f <+47>: pop    %r12
   0x00007ffff6182881 <+49>: pop    %r13
   0x00007ffff6182883 <+51>: retq   
   0x00007ffff6182884 <+52>: nopl   0x0(%rax)
   0x00007ffff6182888 <+56>: movq   $0x0,0x20(%rbx)
   0x00007ffff6182890 <+64>: callq  0x7ffff61790c0 <address@hidden>
   0x00007ffff6182895 <+69>: mov    0x10(%rbx),%rsi
   0x00007ffff6182899 <+73>: mov    %rax,%r13
   0x00007ffff618289c <+76>: mov    %r12,%rdx
   0x00007ffff618289f <+79>: mov    %ebp,%edi
   0x00007ffff61828a1 <+81>: callq  0x7ffff6179130 <address@hidden>
=> 0x00007ffff61828a6 <+86>: mov    %eax,0x0(%r13)
   0x00007ffff61828aa <+90>: add    $0x8,%rsp
   0x00007ffff61828ae <+94>: pop    %rbx
   0x00007ffff61828af <+95>: pop    %rbp
   0x00007ffff61828b0 <+96>: pop    %r12
   0x00007ffff61828b2 <+98>: pop    %r13
   0x00007ffff61828b4 <+100>: retq   


Where this write() calls comes from in the source I am not able to locate, so hard to make patches


--
Stian Skjelstad

reply via email to

[Prev in Thread] Current Thread [Next in Thread]