Skip to content

Commit

Permalink
Add Py_fclose() function
Browse files Browse the repository at this point in the history
  • Loading branch information
vstinner committed Dec 13, 2024
1 parent 773c4d9 commit b80f424
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 4 deletions.
15 changes: 15 additions & 0 deletions Doc/c-api/sys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,28 @@ Operating System Utilities
On success, return the new file object.
On error, set an exception and return ``NULL``.
The file must be closed by :c:func:`Py_fclose` rather than calling directly
``fclose()``.
The file descriptor is created non-inheritable (:pep:`446`).
The caller must hold the GIL.
.. versionadded:: next
.. c:function:: int Py_fclose(FILE *file)
Call ``fclose(file)``.
This function is needed on Windows: ``FILE*`` files opened by
:c:func:`Py_fopen` in the Python DLL must be closed by the Python DLL to use
the same C runtime version. Otherwise, calling ``fclose()`` directly can
cause undefined behavior.
.. versionadded:: next
.. _systemfunctions:
System Functions
Expand Down
3 changes: 2 additions & 1 deletion Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,8 @@ New features

* Add :c:func:`Py_fopen` function to open a file. Similar to the
:c:func:`!fopen` function, but the *path* parameter is a Python object and an
exception is set on error.
exception is set on error. Add also :c:func:`Py_fclose` function to close a
file, function needed for Windows support.
(Contributed by Victor Stinner in :gh:`127350`.)

Porting to Python 3.14
Expand Down
2 changes: 2 additions & 0 deletions Include/cpython/fileutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
PyAPI_FUNC(FILE*) Py_fopen(
PyObject *path,
const char *mode);

PyAPI_FUNC(int) Py_fclose(FILE *file);
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
Add :c:func:`Py_fopen` function to open a file. Similar to the :c:func:`!fopen`
function, but the *path* parameter is a Python object and an exception is set
on error. Patch by Victor Stinner.
on error. Add also :c:func:`Py_fclose` function to close a file, function
needed for Windows support.
Patch by Victor Stinner.
4 changes: 2 additions & 2 deletions Modules/_testcapi/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ _testcapi.py_fopen
mode: str
/
Call Py_fopen() and return fread(256).
Call Py_fopen(), fread(256) and Py_fclose(). Return read bytes.
[clinic start generated code]*/

static PyObject *
Expand All @@ -31,7 +31,7 @@ _testcapi_py_fopen_impl(PyObject *module, PyObject *path, const char *mode)

char buffer[256];
size_t size = fread(buffer, 1, Py_ARRAY_LENGTH(buffer), fp);
fclose(fp);
Py_fclose(fp);

return PyBytes_FromStringAndSize(buffer, size);
}
Expand Down
13 changes: 13 additions & 0 deletions Python/fileutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1836,6 +1836,19 @@ Py_fopen(PyObject *path, const char *mode)
return f;
}


// Call fclose().
//
// This function is needed on Windows: FILE* files opened by Py_fopen() in the
// Python DLL must be closed by the Python DLL to use the same C runtime
// version. Otherwise, calling fclose() directly can cause undefined behavior.
int
Py_fclose(FILE *file)
{
return fclose(file);
}


/* Read count bytes from fd into buf.
On success, return the number of read bytes, it can be lower than count.
Expand Down

0 comments on commit b80f424

Please sign in to comment.