On Dec 17 05:30, Houder wrote: > On 2018-12-16 22:55, Corinna Vinschen wrote: > [snip] > > > I'm mulling over adding some hack to open(). It could try to recognize > > the special case of opening a processes' own descriptor symlink within > > /proc and then warp the open() call into dup(). No idea how tricky > > or even feasible that is, though... > > That is why I wrote the following in my STC: > > // Q: does Cygwin attempt to read the /tmp directory? (an attempt > that > // will fail, because the file has been unlinked) > // it appears that reading a symlnk in /dev/fd can best be diverted > to > // the open file descriptor of the process ... > > What I meant was, that I see no reason to modify the symlink in this > special case, but in stead of that to access the file using fd N, where > N is equal to the one in /dev/fd/N. > > File descriptor N has been left open by bash and should not have been > closed as result of the exec ...
tl;dr: cat tries to open /dev/fd/0. /dev/fd/0 refers to a non-existing file and that's why open fails. Cygwin doesn't have special code to handle the fd symlinks as refference to an actually open descriptors. The long story: The descriptor hasn't been closed. Cat still has the file open as fd 0. The problem is that you tell cat to open and read from /dev/fd/0, *not* from fd 0. That's quite a difference. /dev/fd/0 is just some arbitrary file which is given to open(2), a symlink at that. First thing open(2) does is to call the symlink evaluation code. The symlink is ultimately evaluated to the filename opened by the shell. So, cat's open(2) tries to open "/tmp/whatever". But, as you noticed, that path doesn't exist anymore since it has been deleted by the shell before even writing to it via unlink(2). What happens is that unlink(2) is supposed to delete a file in use. Since that's not possible in Windows, the file gets renamed into the recycle bin and just marked for deletion. The fact that the filename changed is not known to the application of course, it just gets success reported from unlink. Cygwin itself doesn't know the new name of the file either. There just isn't a reason to keep track since it's going to be removed anyway at one point. And even *if* we keep track, we can't use this information since files marked for deletion can't be opened on Windows (ERROR_DELETE_PENDING or ERROR_ACCESS_DENIED, I'm not sure which). Here's another problem with handling /dev/fd/0 as just some descriptor we can call dup(2) on: /dev/fd/0 is just some symlink which evaluates like this: - /dev/fd is a symlink to /proc/self/fd - /proc/self is a symlink to /proc/<current_process_pid> So before we even get to evaluate fd 0 symlink, we're at /proc/<current_process_pid>/fd/0 Here's the question: What if you don't give /proc/self/fd/0 to cat, but something like /proc/<some_other_processes_pid>/fd/0? That's where Cygwin just fails because /proc is a process-local fake in our user space Cygwin DLL. Emulating /proc is fun stuff, the full functionality is pretty tricky without going to great lengths like starting a service with SYSTEM permissions. Bottom line is, we could do more if we decide that running cygserver is a requirement. As it is, we always strived for a setup which works "out of the box", without having to start services and stuff. Corinna -- Corinna Vinschen Cygwin Maintainer
signature.asc
Description: PGP signature