diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -802,6 +802,7 @@ Force write of file with filedescriptor *fd* to disk. On Unix, this calls the native :c:func:`fsync` function; on Windows, the MS :c:func:`_commit` function. + On Mac OS X this calls :c:func:`fcntl` with the :data:`F_FULLFSYNC` value. If you're starting with a buffered Python :term:`file object` *f*, first do ``f.flush()``, and then do ``os.fsync(f.fileno())``, to ensure that all internal diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2125,7 +2125,26 @@ static PyObject * posix_fsync(PyObject *self, PyObject *fdobj) { +#ifdef __APPLE__ + /* Issue 11277 revealed that OS X fsync() does not truly synchronize file + * data to physical backing store, whereas this fcntl does */ + int fd; + int res; + fd = PyObject_AsFileDescriptor(fdobj); + if (fd < 0) + return NULL; + if (!_PyVerify_fd(fd)) + return posix_error(); + Py_BEGIN_ALLOW_THREADS + res = fcntl(fd, F_FULLFSYNC); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; +#else return posix_fildes(fdobj, fsync); +#endif } #endif /* HAVE_FSYNC */