Skip to content

testhelper: Fix ETXTBSY race when writing executables

On Unix-systems, trying to execve(3P) into an executable which is currently open in any process as writeable will result in ETXTBSY errors. We're frequently observing this error in our test suite when using the WriteExecutable() testhelper function.

The root cause of this is a race between fork(3P), execve(3P) and us still having the file descriptor open for writing. Suppose the following race where one thread is trying to write an executable and execute it, and a second thread forking to execute any other executable:

Thread 1                    Thread 2

fd = open(O_WRONLY)
                            fork()
close(fd)
fork()
execve(fd)
                            execve()

We call fork(3P) in the second thread after having opened the file as writeable, which means that the newly created process inherits the writeable file descriptor. And even though we close it in the first thread, execve(3P) will fail with ETXTBSY because it's still open in the second process, which didn't yet call execve(3P) itself and thus hasn't closed the file descriptor until now.

Fix this race by using file locking such that we know that all writeable file descriptors must have been closed at the time of returning from WriteExecutable(). Please refer to 1 for further information about this issue.

Fixes #4018 (closed)

Edited by Patrick Steinhardt

Merge request reports