This behavior seems to be a kind of bug in the /proc virtual file system. If you add this code immediately before opening the file:
system("ls -l /proc/net /proc/self/net/tcp");
You will see that /proc/net is a symbolic link to /proc/self/net , and /proc/sec/net/tcp correctly specified for both open_test calls, even if the call to the spawned stream does not work.
Edit: I just realized that the above test is fictitious, as it will refer to the system call shell process, not this process. Using the following function instead also detects an error:
void ls_command () { ostringstream cmd; cmd << "ls -l /proc/net " << "/proc/" << getpid() << "/net/tcp " << "/proc/" << syscall(SYS_gettid) << "/net/tcp"; system(cmd.str().c_str()); }
You will see that the spawned stream sometimes cannot see the parent file /net/tcp . In fact, it disappeared, since it is a spawned shell process in which the ls is executed.
The workaround below allows the child thread to reliably access what would be its /proc/net/tcp .
My theory is that this is some kind of race condition error with the correct setting of the /proc/self entry for the stream as the correct combination of the parent state and the specific state of the stream. As a test, and I work, I modified the open_test code to use the "process identifier" associated with the thread, instead of trying to access the parent process (since /proc/self refers to the identifier of the parent process, not to the thread).
Edit: As the evidence shows, the error is because the parent process cleared the state /proc/self/... before the child thread got the opportunity to read it. I still claim that this is a mistake, since the child thread is still technically part of the process. It getpid() remains the same before and after calling the main thread pthread_exit() . The /proc entry for the parent process must remain valid until all child threads are complete. Although
Edit2: Jonas claims this may not be a mistake. As evidence of this, there is this from man proc :
/ proc / [pid] / fd
...
In a multithreaded process, the contents of this directory are
not available if the main thread has already terminated (typi-
ally by calling pthread_exit (3)). But then review this entry for /proc/self in the same man entry:
/ proc / self
This directory refers to the process accessing the / proc file
system, and is identical to the / proc directory named by the
process ID of the same process. If you believe that this is not an error, because threads and processes are handled the same way on Linux, then threads should have the expectation that /proc/self will work. The error can be fixed by changing /proc/self to change the value of /proc/[gettid] when the version of /proc/[getpid] no longer available, just as the workaround is below.
void * open_test (void *) { ifstream in; string file = "/proc/net/tcp"; in.open(file.c_str()); if (in.fail()) { ostringstream ss; ss << "/proc/" << syscall(SYS_gettid) << "/net/tcp"; cout << "Can't access " << file << ", using " << ss.str() << " instead" << endl; file = ss.str(); in.open(file.c_str()); } if (in.fail()) cout << "Failed - " << strerror(errno) << endl; else cout << "Succeeded" << endl; in.close(); return 0; }