python / cpython

The Python programming language
https://www.python.org
Other
63.39k stars 30.36k forks source link

seekable() returns True on pipe objects in Windows #86768

Open cbdd7f0d-72f6-46b5-9b22-ea6b9250b1e8 opened 3 years ago

cbdd7f0d-72f6-46b5-9b22-ea6b9250b1e8 commented 3 years ago
BPO 42602
Nosy @pfmoore, @vstinner, @tjguk, @zware, @eryksun, @zooba, @izbyshev

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields: ```python assignee = None closed_at = None created_at = labels = ['type-bug', '3.8', '3.9', 'expert-IO', '3.10', 'OS-windows'] title = 'seekable() returns True on pipe objects in Windows' updated_at = user = 'https://bugs.python.org/nedsociety' ``` bugs.python.org fields: ```python activity = actor = 'izbyshev' assignee = 'none' closed = False closed_date = None closer = None components = ['Windows', 'IO'] creation = creator = 'nedsociety' dependencies = [] files = [] hgrepos = [] issue_num = 42602 keywords = [] message_count = 2.0 messages = ['382746', '382753'] nosy_count = 8.0 nosy_names = ['paul.moore', 'vstinner', 'tim.golden', 'zach.ware', 'eryksun', 'steve.dower', 'izbyshev', 'nedsociety'] pr_nums = [] priority = 'normal' resolution = None stage = None status = 'open' superseder = None type = 'behavior' url = 'https://bugs.python.org/issue42602' versions = ['Python 3.8', 'Python 3.9', 'Python 3.10'] ```

cbdd7f0d-72f6-46b5-9b22-ea6b9250b1e8 commented 3 years ago
>>> import os
>>> r, w = os.pipe()
>>> os.lseek(w, 10, 0)
10
>>> wf = open(w, 'w')
>>> wf.seekable()
True

This happens on Windows. Consequently seek() works for these objects but they seems to be no-op. This may confuse libraries that depend on seeking.

The named pipe objects (via CreateNamedPipe -> open_osfhandle -> open()) exhibit the same behavior.

9b2dd46a-d3b9-42c4-96ed-ebdd39741ebb commented 3 years ago

Yes, despite that MSVCRT knows the type of the file descriptor because it calls GetFileType() on its creation, it doesn't check it in lseek() implementation and simply calls SetFilePointer(), which spuriously succeeds for pipes. MSDN says the following[1]:

Calling the SetFilePointer function with a handle to a non-seeking device such as a pipe or a communications device is not supported, even though the SetFilePointer function may not return an error. The behavior of the SetFilePointer function in this case is undefined.

[1] https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilepointer

PeterJCLaw commented 2 years ago

Would a possible fix here be to check the file type within the (Windows) implementation of seek and seekable? Or is the necessary information not available by that point?

vstinner commented 2 years ago

Maybe Python should get the handle from the file descriptor to call SetFilePointer() on it? Since lseek(fd) seems to silently ignores an error.