Strange echo behaviour

Baruch Siach baruch at tkos.co.il
Thu Jan 27 06:59:39 UTC 2011


Hi Denys,

On Thu, Jan 27, 2011 at 06:18:25AM +0100, Denys Vlasenko wrote:
> On Wednesday 26 January 2011 13:21, Baruch Siach wrote:
> > Hi busybox list,
> > 
> > I'm running the following command under strace (thanks Rob):
> > 
> > echo 56 > /sys/class/gpio/export
> > 
> > and I see the following output:
> > 
> > write(1, "56\n", 3)                     = -1 EBUSY (Device or resource busy)
> > write(1, "5", 1)                        = 1
> > 
> > The first EBUSY is OK, since GPIO 56 is already requested. But the second 
> > write() attempt seems strange, and leads to an unwanted outcome. GPIO 5 gets 
> > exported.
> > 
> > Looking into the code it seems like the fflush() call at the end for 
> > echo_main() is somehow responsible for this, but this is only a guess.
> 
> I would like to make it so that echo doesn't retry failed writes
> (except on EINTR).
> 
> I wonder how to fix this, though. I can easily detect write error,
> but how to discard buffered data in a FILE object?
> Even without fflush(), libc will try to write it out at fclose()!

Here is some more information that may help in understanding this issue.

I've only observed this problem when running a statically linked Busybox 
linked against uClibc 0.9.30.3, and only when running echo directly from the 
shell (ash). When I run

./strace-armv5l echo 56 > /sys/class/gpio/export

I see

write(1, "56\n", 3)                     = -1 EBUSY (Device or resource busy)
write(1, "56\n", 3)                     = -1 EBUSY (Device or resource busy)

as expected, but when I run

./strace-armv5l sh -c 'echo 56 > /sys/class/gpio/export'

I see

write(1, "56\n", 3)                     = -1 EBUSY (Device or resource busy)
write(1, "5", 1)                        = 1

So apparently this problem has something to do with either uClibc or ash, not 
echo.  However, we can implement echo using write(), thus avoiding the 
buffering of stdio.

Another related problem that I've observed with echo goes as follows:

./strace-armv5l sh -c 'echo test > /dev/input/event0'

shows:

write(1, "test\n", 5)                   = 16
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 2147483647) = -1 EFAULT (Bad address)
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4095) = 4096
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 2147483647) = -1 EFAULT (Bad address)
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096

That is, the return value of write() is larger that the written buffer (is 
this legal?) so echo (or ash) tries again with a bogus count == -1.

baruch

-- 
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -


More information about the busybox mailing list