Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-45944: Avoid calling isatty() for most open() calls #29870

Closed
wants to merge 2 commits into from

Conversation

collinanderson
Copy link

@collinanderson collinanderson commented Dec 1, 2021

https://bugs.python.org/issue45944

isatty() is a system call on linux. Most open()s are files, and we're already getting the size of the file. If it has a size, then we know it's not a atty, and can avoid calling it.

https://bugs.python.org/issue45944

Copy link
Member

@tiran tiran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a clever hack!

I made a few suggestions to use correct Py_ssize_t everwhere.

@@ -237,11 +237,13 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,

char rawmode[6], *m;
int line_buffering, is_number;
__int64_t size = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__int64_t size = 0;
Py_ssize_t size = 0;

size_obj = _PyObject_GetAttrId(raw, &PyId__size);
if (size_obj == NULL)
goto error;
size = PyLong_AsLongLong(size_obj);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
size = PyLong_AsLongLong(size_obj);
size = PyLong_AsSsize_t(size_obj);

@@ -66,6 +66,7 @@ typedef struct {
unsigned int closefd : 1;
char finalizing;
unsigned int blksize;
__int64_t size;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__int64_t size;
Py_ssize_t size;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be off_t. The file size can exceed the Py_ssize_t range.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right! size handling depends on platform and support for large file support. You can copy the approach from posixmodule.c:

#ifdef MS_WINDOWS
    typedef long long Py_off_t;
#else
    typedef off_t Py_off_t;
#endif
#ifdef HAVE_LARGEFILE_SUPPORT
    size = (Py_off_t)PyLong_AsLongLong(arg);
#else
    size = (Py_off_t)PyLong_AsLong(arg);
#endif

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is too complicated, we need to duplicate this in several files. But it may be simpler if only cache the boolean result (st_size == 0 or S_IFCHR()) as _maybeatty. Then the size of off_t does not matter.

@@ -469,6 +471,7 @@ _Py_COMP_DIAG_POP
if (fdfstat.st_blksize > 1)
self->blksize = fdfstat.st_blksize;
#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
self->size = fdfstat.st_size;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self->size = fdfstat.st_size;
self->size = fdfstat.st_size;

@@ -1184,6 +1187,7 @@ static PyGetSetDef fileio_getsetlist[] = {

static PyMemberDef fileio_members[] = {
{"_blksize", T_UINT, offsetof(fileio, blksize), 0},
{"_size", T_UINT, offsetof(fileio, size), 0},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{"_size", T_UINT, offsetof(fileio, size), 0},
{"_size", T_PYSSIZET, offsetof(fileio, size), 0},

@github-actions
Copy link

github-actions bot commented Jan 1, 2022

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale Stale PR or inactive for long period of time. label Jan 1, 2022
@eendebakpt
Copy link
Contributor

@collinanderson The PR has gone stale. Can you address the review comments? Or are you ok will someone else picking this up?

@bedevere-app
Copy link

bedevere-app bot commented Nov 28, 2023

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@cmaloney
Copy link
Contributor

cmaloney commented Oct 8, 2024

I think this can be closed now as a fix for bpo-45944 / gh-90102 has been committed and the issue closed out

@skirpichev
Copy link
Member

(And there is no signs of life anyway...)

@skirpichev skirpichev closed this Oct 8, 2024
@collinanderson
Copy link
Author

collinanderson commented Oct 8, 2024

Ohh awesome. Thank you! Yeah Sorry I'm not much of a C programmer. I'm super excited to see #120754 syscalls being optimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting review stale Stale PR or inactive for long period of time.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants