On 2018-10-06 22:12, Paul Eggert wrote:
[snip}

My guess is that you've got an old version of grep on Cygwin, and need
to upgrade to the current version. If you still have problems with the
latest version, please investigate via GDB and/or other means exactly
why grep is failing for you ...

Hi Paul,

I have found what causes grep to fail. (after building v3.1 of grep)

But in order not to mislead others reading this thread, I must correct what I wrote in my initial post. There I wrote: "as far as I can tell, the code that is executed on Cygwin is not the same as the one that is executed on Linux".

Wrong. My "strace-ing" misled me.

Returning to grep's failure on Gygwin:

grep terminates with an error on Cygwin because lseek() on Cygwin fails to
ascertain that it is applied to a FIFO.

As result Cygwin's executive returns EINVAL in errno, in stead of ESPIPE, as
required (my interpretation after reading "man 2 lseek").

ESPIPE is expected in reset() (src/grep.c), after lseek() has been applied to
stdin (which points to a FIFO here).

Until v2.26 of grep, a call to S_ISREG(st->st_mode) circumvented the call to lseek() (and the call to suppressible_error()) and made reset() return true.

Version v2.27 of grep removed the call to S_ISREG(st->st_mode). As result of
that lseek() is invoked.

lseek() fails, but an exception is made for errno == ESPIPE. For this reason
grep does not fail on Linux (reset() returns true).

However on Cygwin, suppressible_error() is called and reset() returns false,
which makes grep fail on Cygwin.

You can see for yourself in the attached logfiles (GDB sessions).

-----
To what did I apply GDB?

- downloaded the tarball (grep-3.1.tar.xz) from http://ftp.gnu.org/gnu/grep/
 - build grep using "make CFLAG='-O -g3'", both on Linux and Cygwin

Regards,
Henri
64-@@ gdb /drv/e/grep/b3.1/src/grep
GNU gdb (GDB) (Cygwin 7.12.1-2) 7.12.1
...

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /drv/e/grep/b3.1/src/grep...done.
(gdb) set args .
(gdb) br main
Breakpoint 1 at 0x10040419a: file ../../grep-3.1/src/grep.c, line 2415.
(gdb) br reset
Breakpoint 2 at 0x1004032bc: file ../../grep-3.1/src/grep.c, line 847.
(gdb) br grep.c:856 <==== break-point on "if (seek_failed)" in grep.c/reset()
Breakpoint 3 at 0x100403850: file ../../grep-3.1/src/grep.c, line 856.
(gdb) run
Starting program: /drv/e/grep/b3.1/src/grep .
[New Thread 4684.0xe28]
[New Thread 4684.0x834]

Thread 1 hit Breakpoint 1, main (argc=2, argv=0xffffcc40) at 
../../grep-3.1/src/grep.c:2415
2415    {
(gdb) p dup2(open("fifo", 0), 0) # make stdin refer to the fifo ...
<GDB does not return because the open() call blocks>

    Using another terminal, execute: echo aaa > fifo (open() for write resumes 
the open() call above)

$1 = 0
(gdb) cont
Continuing.

Thread 1 hit Breakpoint 2, grep (ineof=<synthetic pointer>, st=0xffffc940, 
fd=0) at ../../grep-3.1/src/grep.c:1447
1447      if (! reset (fd, st))
(gdb) cont
Continuing.

Thread 1 hit Breakpoint 3, reset (st=0xffffc940, fd=0) at 
../../grep-3.1/src/grep.c:856
856       if (seek_failed)
(gdb) p seek_failed
$2 = true
(gdb) p bufoffset
$3 = -1
(gdb) p errno
$4 = 22           # EINVAL, because NT returns ERROR_INVALID_PARAMETER (= 87)
(gdb) p errno=29  # replace w/ ESPIPE (= illegal seek)
$5 = 29
(gdb) cont
Continuing.
aaa               # output of grep as expected/desired
[Inferior 1 (process 4684) exited normally]
(gdb) quit
64-@@ 

Q: why is the fifo not recognized as a pipe by Cygwin? (why does Linux 
recognize it a fifo/pipe?)

=====
@@ gdb /home/proj/grep/b3.1/src/grep
GNU gdb (GDB) Fedora 7.11.1-86.fc24
...

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /home/proj/grep/b3.1/src/grep...done.
(gdb) set args . < fifo
(gdb) br reset
Breakpoint 1 at 0x4050c2: file ../../grep-3.1/src/grep.c, line 847.
(gdb) br grep.c:856 <==== break-point on "if (seek_failed)" in grep.c/reset()
Breakpoint 2 at 0x4055d6: file ../../grep-3.1/src/grep.c, line 856.
(gdb) run
Starting program: /home/proj/grep/b3.1/src/grep . < fifo
<GDB does not return because the open() call blocks>

    Using another terminal, execute: echo aaa > fifo (open() for write resumes 
the open() call above)

Missing separate debuginfos, use: dnf debuginfo-install 
glibc-2.23.1-12.fc24.x86_64
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Breakpoint 1, grep (ineof=<synthetic pointer>, st=0x7fffffffdaa0, fd=0) at 
../../grep-3.1/src/grep.c:1447
1447      if (! reset (fd, st))
Missing separate debuginfos, use: dnf debuginfo-install pcre-8.41-1.fc24.x86_64
(gdb) cont
Continuing.

Breakpoint 2, reset (st=0x7fffffffdaa0, fd=0) at ../../grep-3.1/src/grep.c:856
856       if (seek_failed)
(gdb) p seek_failed
$1 = true
(gdb) p bufoffset
$2 = -1
(gdb) p errno
$3 = 29           # ESPIPE (= illegal seek)
(gdb) cont
Continuing.
aaa               # output of grep as expected/desired
[Inferior 1 (process 10652) exited normally]
(gdb)  quit
@@ 

=====

Reply via email to