Comment 1 for bug 1295366

Revision history for this message
Kovid Goyal (kovid) wrote :

I cannot replicate this with python 2.7.6 on my gentoo system. See the test below:

$ python -c "f = open('/tmp/test', 'wb'); f.write('abcd'); f.close(); f = open('/tmp/test', 'a+b'); f.seek(0); f.truncate(); f.write('abcd'); f.close(); print (open('/tmp/test').read()); import sys; print sys.version"
abcd
2.7.6 (default, Dec 3 2013, 21:15:46)
[GCC 4.8.2]

As you can see, seek(0) followed by truncate() works as expected on python 2.7.6.

IIRC, the python file object is just a thin wrapper around the libc FILE* pointer. So I suspect that this has something to do with a change in how truncate works in whatever C library your system is using. It seems rather odd that something as fundamental as the C library would change the behavior of something as widely used as truncate(), but...

You cannot change a+b to r+b. That would break when the file being used does not exist. That was the entire reason for using a+b in the first place. Using r+b will break, for example, the set() method of the Config class in config_base.py

The only way to accommodate your broken libc would be to first try to open the file in r+b and then fallback to w+b. There is a race condition in that. It annoys me to be forced to use code that is vulnerable to a race condition just to accommodate one distro's broken libc.

It may be possible to open in r+b and promote to w+b using fcntl, I will have to look into that.

What version/implementation of libc is your system using?