Subject: Re: coreutils-8.14, "rm -r" fails with EBADF

From: Jim Meyering <[email-masked]>
Date: Thu, 15 Dec 2011 17:28:31 +0100

Joachim Schmitz wrote:
...
>> but what I really need to know is what happened just prior, in fts_read.
>> Can you run gdb, set a breakpoint in fts_read and show us the result of stepping
>> through fts_read?  That would be most useful.
>
> Sorry, no gdb, the debugger here is calls eInspect (but is similar to
> gdb, as far as I know).
> It goes thru fts_read() the 1st time without problem, on 2nd round
> fts_build(sp, BREAD) in ~/coreutils-8.14/lib/fts.c line 903 returns
> NULL, then the subsequent rm_fts (fts, ent, x) fails. It goues trhi
> fts_read() 2 more times after that.

There are three places in fts_build that directly set FTS_STOP:

  - fts_palloc failure (i.e., virtual memory exhausted, not likely)
  - found a file name longer than SIZE_MAX (not likely)
  - failure to restore working directory:

        /*
         * If descended after called from fts_children or after called from
         * fts_read and nothing found, get back.  At the root level we use
         * the saved fd; if one of fts_open()'s arguments is a relative name
         * to an empty directory, we wind up here with no other way back.  If
         * can't get back, we're done.
         */
        if (!continue_readdir && descend && (type == BCHILD || !nitems) &&
            (cur->fts_level == FTS_ROOTLEVEL
             ? RESTORE_INITIAL_CWD(sp)
             : fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
                cur->fts_info = FTS_ERR;
                SET(FTS_STOP);
                fts_lfree(head);
                return (NULL);
        }

If you can debug it further to narrow down what/how it is failing,
eventually we'll find the cause.