diff -r 9dc66b3a1d0d -r b937912fdd6f Doc/library/os.rst --- a/Doc/library/os.rst Wed Jul 23 22:56:55 2014 +0200 +++ b/Doc/library/os.rst Wed Jul 23 23:30:30 2014 +0200 @@ -801,6 +801,17 @@ as internal buffering of data. Availability: Unix. +.. function:: get_blocking(fd) + + Get the blocking mode of the file descriptor: ``False`` if the + :data:`O_NONBLOCK` flag is set, ``True`` if the flag is cleared. + + See also :func:`set_blocking` and :meth:`socket.socket.setblocking`. + + Availability: Unix. + + .. versionadded:: 3.5 + .. function:: isatty(fd) Return ``True`` if the file descriptor *fd* is open and connected to a @@ -1101,6 +1112,18 @@ or `the MSDN bool\n" \ + "\n" \ + "Get the blocking mode of the file descriptor:\n" \ + "False if the O_NONBLOCK flag is set, True if the flag is cleared."); + +static PyObject* +posix_get_blocking(PyObject *self, PyObject *args) +{ + int fd; + int blocking; + + if (!PyArg_ParseTuple(args, "i:get_blocking", &fd)) + return NULL; + + if (!_PyVerify_fd(fd)) + return posix_error(); + + blocking = _Py_get_blocking(fd); + if (blocking < 0) + return NULL; + return PyBool_FromLong(blocking); +} + +PyDoc_STRVAR(set_blocking__doc__, + "set_blocking(fd, blocking)\n" \ + "\n" \ + "Set the blocking mode of the specified file descriptor.\n" \ + "Set the O_NONBLOCK flag if blocking is False,\n" \ + "clear the O_NONBLOCK flag otherwise."); + +static PyObject* +posix_set_blocking(PyObject *self, PyObject *args) +{ + int fd, blocking; + + if (!PyArg_ParseTuple(args, "ii:set_blocking", &fd, &blocking)) + return NULL; + + if (!_PyVerify_fd(fd)) + return posix_error(); + + if (_Py_set_blocking(fd, blocking) < 0) + return NULL; + Py_RETURN_NONE; +} +#endif /* !MS_WINDOWS */ + + /*[clinic input] dump buffer [clinic start generated code]*/ @@ -11606,6 +11656,10 @@ static PyMethodDef posix_methods[] = { {"set_handle_inheritable", posix_set_handle_inheritable, METH_VARARGS, set_handle_inheritable__doc__}, #endif +#ifndef MS_WINDOWS + {"get_blocking", posix_get_blocking, METH_VARARGS, get_blocking__doc__}, + {"set_blocking", posix_set_blocking, METH_VARARGS, set_blocking__doc__}, +#endif {NULL, NULL} /* Sentinel */ }; diff -r 9dc66b3a1d0d -r b937912fdd6f Python/fileutils.c --- a/Python/fileutils.c Wed Jul 23 22:56:55 2014 +0200 +++ b/Python/fileutils.c Wed Jul 23 23:30:30 2014 +0200 @@ -1045,3 +1045,57 @@ int return fd; } +#ifndef MS_WINDOWS +/* Get the blocking mode of the file descriptor. + Return 0 if the O_NONBLOCK flag is set, 1 if the flag is cleared, + raise an exception and return -1 on error. */ +int +_Py_get_blocking(int fd) +{ + int flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + + return !(flags & O_NONBLOCK); +} + +/* Set the blocking mode of the specified file descriptor. + + Set the O_NONBLOCK flag if blocking is False, clear the O_NONBLOCK flag + otherwise. + + Return 0 on success, raise an exception and return -1 on error. */ +int +_Py_set_blocking(int fd, int blocking) +{ +#if defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO) + int arg = !blocking; + if (ioctl(fd, FIONBIO, &arg) < 0) + goto error; +#else + int flags, res; + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) + goto error; + + if (blocking) + flags = flags & (~O_NONBLOCK); + else + flags = flags | O_NONBLOCK; + + res = fcntl(fd, F_SETFL, flags); + if (res < 0) + goto error; + +#endif + return 0; + +error: + PyErr_SetFromErrno(PyExc_OSError); + return -1; +} +#endif +