Hello. I am encountering this bug too. I would like to compile grep 2.21 for Windows using mingw-w64 and Git Bash. But the grep that I end up compiling exhibits several bugs related to recursive operation. To reproduce the bugs, I made a directory called "testdir" with two empty directories named "a" and "b" inside it. I used "cd" to go into the testdir.
Here is a shell session showing bug A: $ ../src/grep.exe a -r c:\Users\David\Documents\grep\grep-2.21\src\grep.exe: 9: Bad file descriptor Here is a shell session showing bug B: $ ../src/grep.exe a -R c:\Users\David\Documents\grep\grep-2.21\src\grep.exe: warning: a: recursive directory loop c:\Users\David\Documents\grep\grep-2.21\src\grep.exe: warning: b: recursive directory loop Bug A is more important because it prevents grep from printing the desired output, so I am focussing on it first. I think I have narrowed it down enough to determine that it is actually a bug in the fts implementation from gnulib, or in one of its dependencies (like mingw-w64 of msvcrt.dll). If I put this small block of code at the top of main, it causes the same error: { // tmphax program_name = "silly"; filename = "emptydir"; char *fts_arg[2]; fts_arg[0] = (char *)filename; fts_arg[1] = NULL; int fts_opts = FTS_CWDFD | FTS_NOSTAT | FTS_TIGHT_CYCLE_CHECK | FTS_COMFOLLOW | FTS_PHYSICAL; FTS *fts = fts_open(fts_arg, fts_opts, NULL); printf("fts_open returned %p\n", fts); FTSENT *ent; ent = fts_read(fts); ent = fts_read(fts); printf(" fts_path= %s\n", ent->fts_path); printf(" fts_accpath=%s\n", ent->fts_accpath); printf(" fts_name= %s\n", ent->fts_name); if(ent->fts_info == FTS_ERR) { printf(" fts_info= FTS_ERR\n"); suppressible_error(filename, ent->fts_errno); } return 36; } Note that "emptydir" is a directory inside the CWD that is empty. The output from that block of code is: fts_open returned 008222B0 fts_path= emptydir fts_accpath=emptydir fts_name= emptydir fts_info= FTS_ERR silly: emptydir: Bad file descriptor I noticed that the Git repository for gnulib has some recent bug fixes for the fts implementation, so I tried copying the fts* files from gnulib commit 0f4fa16 into grep's lib directory, but that did not make any difference. My next step will probably be to take grep out of the picture and report this as a bug to the gnulib team (or find an existing bug report, like the one mentioned earlier in this thread). Note that for Bug A, grep doesn't print "9" as the filename in the error message every time. It seems to be printing a random character that is different each time, because grep is reading beyond the bounds of a string and probably doing undefined behavior! We can call that Bug C. If a grep maintainer is interested in fixing Bug C, they should improve the logic at this line in grepdirent in grep.c: filename = ent->fts_path + filename_prefix_len; If you run "grep a -r" then it seems that fts_path can be ".", while filename_prefix_len is 2. So it is really bad to execute the line above in that case, because filename will be set to point past the end of the string and then later used when printing error messages. I hope this was helpful. --David Grayson