classification
Title: os.posix_fadvise misreports errors
Type: Stage: resolved
Components: IO, Library (Lib) Versions: Python 3.6
process
Status: closed Resolution: duplicate
Dependencies: Superseder: os.posix_fallocate() generate exception with errno 0
View: 31106
Assigned To: Nosy List: ZackerySpytz, enkore
Priority: normal Keywords:

Created on 2017-01-22 11:20 by enkore, last changed 2018-07-11 04:41 by benjamin.peterson. This issue is now closed.

Messages (3)
msg286002 - (view) Author: Marian Beermann (enkore) Date: 2017-01-22 11:20
It has been observed that posix_fadvise will not report the original error if the syscall fails. Eg. https://bugs.alpinelinux.org/issues/6592

>>> os.posix_fadvise(-1, 0, 0, os.POSIX_FADV_DONTNEED)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 0] Error

Should report EBADF

>>> os.posix_fadvise(16, 0, 0, os.POSIX_FADV_DONTNEED)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 0] Error

Ditto

>>> os.posix_fadvise(0, 0, 0, 12345)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 0] Error

Should be EINVAL

...

This might be because unlike most syscall wrappers posix_fadvise does not set errno but only returns it.
msg286003 - (view) Author: Marian Beermann (enkore) Date: 2017-01-22 11:24
Indeed, os.posix_fadvise tries to fetch the error from errno, via posix_error()

static PyObject *
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
                      Py_off_t length, int advice)
/*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
{
    int result;
    int async_err = 0;

    do {
        Py_BEGIN_ALLOW_THREADS
        result = posix_fadvise(fd, offset, length, advice);
        Py_END_ALLOW_THREADS
    } while (result != 0 && errno == EINTR &&
             !(async_err = PyErr_CheckSignals()));
    if (result != 0)
        return (!async_err) ? posix_error() : NULL;
    Py_RETURN_NONE;
}

------------------------------^ posix_error() using errno not result

posix_fallocate has the same caveat and mishandles errors as well:

static PyObject *
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
                        Py_off_t length)
/*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
{
    int result;
    int async_err = 0;

    do {
        Py_BEGIN_ALLOW_THREADS
        result = posix_fallocate(fd, offset, length);
        Py_END_ALLOW_THREADS
    } while (result != 0 && errno == EINTR &&
             !(async_err = PyErr_CheckSignals()));
    if (result != 0)
        return (!async_err) ? posix_error() : NULL;
    Py_RETURN_NONE;
}

------------------------------^ posix_error() using errno not result
msg321403 - (view) Author: Zackery Spytz (ZackerySpytz) * (Python triager) Date: 2018-07-11 00:11
This was fixed in #31106.
History
Date User Action Args
2018-07-11 04:41:31benjamin.petersonsetstatus: open -> closed
superseder: os.posix_fallocate() generate exception with errno 0
resolution: duplicate
stage: resolved
2018-07-11 00:11:52ZackerySpytzsetnosy: + ZackerySpytz
messages: + msg321403
2017-01-22 11:24:41enkoresetmessages: + msg286003
2017-01-22 11:20:17enkorecreate