t.i.serialport.Serialport().flushInput() causes exception on Windows
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 6k
- Forks
- 1.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 10
Description
| @altendky reported | |
|---|---|
| Trac ID | trac#9720 |
| Type | defect |
| Created | 2019-10-24 00:06:59Z |
Flushing serial input on Windows causes the twisted internal read operations to be canceled. Given that the flush/reset is being requested through twisted it seems like we should be able to handle this temporarily expected exception. We may also want to clear some internal buffers, I don't recall how that works at the moment. I'll see if I can come up with a sensible PR.
pywintypes.error: (995, 'GetOverlappedResult', 'The I/O operation has been aborted because of either a thread exit or an application request.')
Flushing in pyserial has long been doing the same by passing the abort flag.
win32file.PurgeComm(self.hComPort, win32file.PURGE_RXCLEAR | win32file.PURGE_RXABORT)
win32.PurgeComm(self._port_handle, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
Here's the log of creating the issue with the contrived serial.win32.PurgeComm() call.
PS C:\epc\test-software> py -3.7-64 -m venv venv
PS C:\epc\test-software> venv/scripts/pip install twisted pywin32 pyserial
Collecting twisted
Using cached https://files.pythonhosted.org/packages/ee/d9/5b79fef4a7d7dc4d526151904eae5dd207f80433ae646a258b32abbe77d4/Twisted-19.7.0-cp37-cp37m-win_amd64.whl
Collecting pywin32
Using cached https://files.pythonhosted.org/packages/b5/26/801bc6d99612977accac84b2d8ad06efa4a7d831c5e2813ca9baf700b646/pywin32-225-cp37-cp37m-win_amd64.whl
Collecting pyserial
Using cached https://files.pythonhosted.org/packages/0d/e4/2a744dd9e3be04a0c0907414e2a01a7c88bb3915cbe3c8cc06e209f59c30/pyserial-3.4-py2.py3-none-any.whl
Collecting incremental>=16.10.1 (from twisted)
Using cached https://files.pythonhosted.org/packages/f5/1d/c98a587dc06e107115cf4a58b49de20b19222c83d75335a192052af4c4b7/incremental-17.5.0-py2.py3-none-any.whl
Collecting PyHamcrest>=1.9.0 (from twisted)
Using cached https://files.pythonhosted.org/packages/9a/d5/d37fd731b7d0e91afcc84577edeccf4638b4f9b82f5ffe2f8b62e2ddc609/PyHamcrest-1.9.0-py2.py3-none-any.whl
Collecting constantly>=15.1 (from twisted)
Using cached https://files.pythonhosted.org/packages/b9/65/48c1909d0c0aeae6c10213340ce682db01b48ea900a7d9fce7a7910ff318/constantly-15.1.0-py2.py3-none-any.whl
Collecting hyperlink>=17.1.1 (from twisted)
Using cached https://files.pythonhosted.org/packages/7f/91/e916ca10a2de1cb7101a9b24da546fb90ee14629e23160086cf3361c4fb8/hyperlink-19.0.0-py2.py3-none-any.whl
Collecting attrs>=17.4.0 (from twisted)
Using cached https://files.pythonhosted.org/packages/a2/db/4313ab3be961f7a763066401fb77f7748373b6094076ae2bda2806988af6/attrs-19.3.0-py2.py3-none-any.whl
Collecting zope.interface>=4.4.2 (from twisted)
Using cached https://files.pythonhosted.org/packages/a8/d2/e2fb1052cdf1c1d05a23c5f7a192a8dc104d5afda0539f86b9839264e1cc/zope.interface-4.6.0-cp37-cp37m-win_amd64.whl
Collecting Automat>=0.3.0 (from twisted)
Using cached https://files.pythonhosted.org/packages/e5/11/756922e977bb296a79ccf38e8d45cafee446733157d59bcd751d3aee57f5/Automat-0.8.0-py2.py3-none-any.whl
Collecting six (from PyHamcrest>=1.9.0->twisted)
Using cached https://files.pythonhosted.org/packages/73/fb/00a976f728d0d1fecfe898238ce23f502a721c0ac0ecfedb80e0d88c64e9/six-1.12.0-py2.py3-none-any.whl
Requirement already satisfied: setuptools in c:\epc\test-software\venv\lib\site-packages (from PyHamcrest>=1.9.0->twisted) (40.8.0)
Collecting idna>=2.5 (from hyperlink>=17.1.1->twisted)
Using cached https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl
Installing collected packages: incremental, six, PyHamcrest, constantly, idna, hyperlink, attrs, zope.interface, Automat, twisted, pywin32, pyserial
Successfully installed Automat-0.8.0 PyHamcrest-1.9.0 attrs-19.3.0 constantly-15.1.0 hyperlink-19.0.0 idna-2.8 incremental-17.5.0 pyserial-3.4 pywin32-225 six-1.12.0 twisted-19.7.0 zope.interface-4.6.0
You are using pip version 19.0.3, however version 19.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.
PS C:\epc\test-software> venv/scripts/python --version --version
Python 3.7.4 (tags/v3.7.4:e09359112e, Jul 8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)]
PS C:\epc\test-software> venv/scripts/pip freeze
attrs==19.3.0
Automat==0.8.0
constantly==15.1.0
hyperlink==19.0.0
idna==2.8
incremental==17.5.0
PyHamcrest==1.9.0
pyserial==3.4
pywin32==225
six==1.12.0
Twisted==19.7.0
zope.interface==4.6.0
First the non-failing output.
PS C:\epc\test-software> venv/scripts/python example.py
---- CHECKPOINT: a
---- CHECKPOINT: b
---- CHECKPOINT: c
Here is the basic failure.
PS C:\epc\test-software> venv/scripts/python example.py --fail
---- CHECKPOINT: a
---- CHECKPOINT: b
Unhandled Error
Traceback (most recent call last):
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1283, in run
self.mainLoop()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1292, in mainLoop
self.runUntilCurrent()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 886, in runUntilCurrent
f(*a, **kw)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\threads.py", line 117, in _callFromThread
result = defer.maybeDeferred(f, *a, **kw)
--- <exception caught here> ---
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 300, in _runAction
closed = getattr(fd, action)()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 349, in _execute
self._reactor, lambda: getattr(self._fd, self._action)())
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\threads.py", line 122, in blockingCallFromThread
result.raiseException()
File "C:\epc\test-software\venv\lib\site-packages\twisted\python\failure.py", line 488, in raiseException
raise self.value.with_traceback(self.tb)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\defer.py", line 151, in maybeDeferred
result = f(*args, **kw)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 349, in <lambda>
self._reactor, lambda: getattr(self._fd, self._action)())
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\_win32serialport.py", line 80, in serialReadEvent
n = win32file.GetOverlappedResult(self._serial._port_handle, self._overlappedRead, 0)
pywintypes.error: (995, 'GetOverlappedResult', 'The I/O operation has been aborted because of either a thread exit or an application request.')
---- CHECKPOINT: c
And another mode of failure that additionally includes a couple builtins.KeyError exceptions.
PS C:\epc\test-software> venv/scripts/python example.py --fail
---- CHECKPOINT: a
---- CHECKPOINT: b
Unhandled Error
Traceback (most recent call last):
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1283, in run
self.mainLoop()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1292, in mainLoop
self.runUntilCurrent()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 886, in runUntilCurrent
f(*a, **kw)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\threads.py", line 117, in _callFromThread
result = defer.maybeDeferred(f, *a, **kw)
--- <exception caught here> ---
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 300, in _runAction
closed = getattr(fd, action)()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 349, in _execute
self._reactor, lambda: getattr(self._fd, self._action)())
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\threads.py", line 122, in blockingCallFromThread
result.raiseException()
File "C:\epc\test-software\venv\lib\site-packages\twisted\python\failure.py", line 488, in raiseException
raise self.value.with_traceback(self.tb)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\defer.py", line 151, in maybeDeferred
result = f(*args, **kw)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 349, in <lambda>
self._reactor, lambda: getattr(self._fd, self._action)())
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\_win32serialport.py", line 80, in serialReadEvent
n = win32file.GetOverlappedResult(self._serial._port_handle, self._overlappedRead, 0)
pywintypes.error: (995, 'GetOverlappedResult', 'The I/O operation has been aborted because of either a thread exit or an application request.')
Unhandled Error
Traceback (most recent call last):
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1283, in run
self.mainLoop()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1292, in mainLoop
self.runUntilCurrent()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 886, in runUntilCurrent
f(*a, **kw)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\threads.py", line 117, in _callFromThread
result = defer.maybeDeferred(f, *a, **kw)
--- <exception caught here> ---
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 300, in _runAction
closed = getattr(fd, action)()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 349, in _execute
self._reactor, lambda: getattr(self._fd, self._action)())
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\threads.py", line 122, in blockingCallFromThread
result.raiseException()
File "C:\epc\test-software\venv\lib\site-packages\twisted\python\failure.py", line 488, in raiseException
raise self.value.with_traceback(self.tb)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\defer.py", line 151, in maybeDeferred
result = f(*args, **kw)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 349, in <lambda>
self._reactor, lambda: getattr(self._fd, self._action)())
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\_win32serialport.py", line 80, in serialReadEvent
n = win32file.GetOverlappedResult(self._serial._port_handle, self._overlappedRead, 0)
pywintypes.error: (995, 'GetOverlappedResult', 'The I/O operation has been aborted because of either a thread exit or an application request.')
Unhandled Error
Traceback (most recent call last):
File "C:\Program Files\Python37\lib\threading.py", line 926, in _bootstrap_inner
self.run()
File "C:\Program Files\Python37\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1283, in run
self.mainLoop()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1292, in mainLoop
self.runUntilCurrent()
--- <exception caught here> ---
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 886, in runUntilCurrent
f(*a, **kw)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 154, in removeEvent
del self._events[event]
builtins.KeyError: <PyHANDLE:780>
Unhandled Error
Traceback (most recent call last):
File "C:\Program Files\Python37\lib\threading.py", line 926, in _bootstrap_inner
self.run()
File "C:\Program Files\Python37\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1283, in run
self.mainLoop()
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 1292, in mainLoop
self.runUntilCurrent()
--- <exception caught here> ---
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\base.py", line 886, in runUntilCurrent
f(*a, **kw)
File "C:\epc\test-software\venv\lib\site-packages\twisted\internet\win32eventreactor.py", line 154, in removeEvent
del self._events[event]
builtins.KeyError: <PyHANDLE:708>
---- CHECKPOINT: c
PS C:\epc\test-software> type example.py
import argparse
import sys
import twisted.internet.defer
import twisted.internet.serialport
import twisted.internet.task
import serial.win32
@twisted.internet.defer.inlineCallbacks
def go(reactor, port, baud_rate, parity, fail):
protocol = twisted.internet.protocol.Protocol()
port = twisted.internet.serialport.SerialPort(
protocol=protocol,
deviceNameOrPortNumber=port,
reactor=reactor,
baudrate=baud_rate,
bytesize=8,
parity=parity,
stopbits=1,
xonxoff=False,
rtscts=False,
)
print(' ---- CHECKPOINT: a', file=sys.stderr)
# port.flushInput() / port._serial.reset_input_buffer()
flags = serial.win32.PURGE_RXCLEAR
if fail:
flags |= serial.win32.PURGE_RXABORT
serial.win32.PurgeComm(
port._serial._port_handle,
flags,
)
print(' ---- CHECKPOINT: b', file=sys.stderr)
yield twisted.internet.task.deferLater(
twisted.internet.reactor,
1,
lambda: None,
)
print(' ---- CHECKPOINT: c', file=sys.stderr)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--port', default='com4')
parser.add_argument('--baud-rate', type=int, default=19200)
parser.add_argument('--parity', default='N')
parser.add_argument('--fail', action='store_true')
args = parser.parse_args()
twisted.internet.task.react(
go,
(args.port, args.baud_rate, args.parity, args.fail),
)
main()
Searchable metadata
trac-id__9720 9720
type__defect defect
reporter__altendky altendky
priority__normal normal
milestone__None None
branch__
branch_author__
status__new new
resolution__None None
component__core core
keywords__None None
time__1571875619218458 1571875619218458
changetime__1571875647116033 1571875647116033
version__None None
owner__altendky altendky
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with twisted/internet/_win32serialport.py at serialReadEvent and follow the related win32eventreactor.py paths shown in the traceback. Reproduce the Windows flushInput case using the reported failure mode, then verify that the expected canceled read does not produce unhandled errors or leave inconsistent internal event state.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- networking, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100