Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reading child /proc/<pid>/stat after exec #1353

Closed
therealkenc opened this issue Nov 12, 2016 · 6 comments
Closed

Reading child /proc/<pid>/stat after exec #1353

therealkenc opened this issue Nov 12, 2016 · 6 comments

Comments

@therealkenc
Copy link
Collaborator

therealkenc commented Nov 12, 2016

This one is painful to look at. The test case below tries to open /proc/<pid>/stat on a process that is just about to die. I'd call the whole construct "broken", but it exists.

You can make an awfully strong case that the child process isn't guaranteed to be alive at the point the stat file is opened in the parent, but for reasons, this always seems to be the case on Real Linux™. WSL strace here and Linux strace here. Don't dwell on the straces though; the error is No such file or directory on /proc/pid/stat because that process is gone.

[edit- delete poor speculation]. Whatever the reason, it isn't dumb luck; you can uncomment the sleep() call after the else, but no matter how long you hang around, the proc/<pid> entry is still there long after the child /bin/echo process has had a chance to finish. 14959.

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char* argv[]) {    
  int pipe_fds[2];
  pipe(pipe_fds);
  
  pid_t pid = fork();
  if (pid == 0) {
    dup2(pipe_fds[1], STDOUT_FILENO);
    execl("/bin/echo", "echo", "hello", NULL);
    // notreached
  } else {
    //sleep(2);
    const size_t buf_sz = 4096;
    char output_buf[buf_sz];
    int output_nread = read(pipe_fds[0], output_buf, buf_sz);
    printf("got from child: %s", output_buf);

    char path[buf_sz];
    snprintf(path, buf_sz, "/proc/%d/stat", pid);
    int fd = open(path, O_RDONLY);
    if (fd < 0) {
      fprintf(stderr, "open %s failed: ", path);
      perror("");
      _exit(-1);
    }

    char stat_buf[buf_sz];
    ssize_t stat_nread = read(fd, stat_buf, buf_sz);
    if (stat_nread < 0) {
      perror("failed to read: ");
      _exit(-1);
    }
    printf("stat for pid %d:\n%s", pid, stat_buf);
  }

  return 0;
}
@stehufntdev
Copy link
Collaborator

Thanks for reporting the issue. This is a known issue where procfs in WSL does not handle zombie processes correctly. Can you please let us know what scenario this is blocking so we can prioritize?

@therealkenc
Copy link
Collaborator Author

therealkenc commented Nov 14, 2016

I linked the scenario in it exists above. It's how the chromium base library gets the parent process id of a given process id, independent of parent/child relationship of the caller. [There's no explicit posix construct for such a thing.]

@Brian-Perkins
Copy link

This should work better starting in Insider Build 17713

@therealkenc
Copy link
Collaborator Author

Brian - #2786 too then probably (it was almost duped)

@Brian-Perkins
Copy link

@therealkenc -- agreed, added a comment there as well.

@mqudsi
Copy link

mqudsi commented Sep 29, 2018

fwiw, indeed it isn't dumb luck that the process entry is still around after the process exits. Until a call to waitpid() from the parent process (presuming the parent process is still around and SIGCHILD doesn't get kicked up to init), Real Linux keeps the process structure around in the kernel (leading to a "zombie" process which has exited but remains visible in process managers).

mqudsi added a commit to mqudsi/fish-shell that referenced this issue Sep 30, 2018
MSFT addressed this in Windows 10 build 17713, but that's not included
in any public releases yet, so keep that around for a little while
longer.

ref microsoft/WSL#2786
ref microsoft/WSL#1353
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants