omz / Pythonista-Issues

Issue tracker for Pythonista (iOS)
169 stars 14 forks source link

(websocket)when the network is bad, it shows “Fatal read error on socket transport”. #563

Closed yjqiang closed 5 years ago

yjqiang commented 6 years ago

https://github.com/aio-libs/aiohttp/issues/3202

According to the authors of aiohttp, it is a bug in pythonista.

cclauss commented 6 years ago

Please change the title of this issue to something more descriptive. There a lot of open issues and the current title does nothing to help those who are trying to find and fix issues.

jsbain commented 6 years ago

How about some example code which allows someone to reproduce your failure. The aiohttp folks said this was not their code, but didn't absolve your usage either...

yjqiang commented 6 years ago

https://github.com/yjqiang/bilibili-live-tools/blob/master/connect.py

https://github.com/yjqiang/bilibili-live-tools/blob/master/bilibiliCilent.py

yjqiang commented 6 years ago

I used "try" to catch the exceptions. But I can't catch the "fatal error" msg.

dgelessus commented 6 years ago

Isn't this the same issue that was discussed in #555?

yjqiang commented 6 years ago

Sorry about that, at first I thought it was aiohttp client's bug, but I wrote only one websocket using aiohttp, and it showed again. And I also tried https://github.com/aaugustin/websockets to use websocket, it showed again and again.

yjqiang commented 5 years ago

I think it should be the bug in pythonista.

jsbain commented 5 years ago

So, can you summarize how we reproduce this error? Seems like there should be a very succinct script with a few lines that reproduces the issue. Does this fail when the network is off? Or does it need interaction with the server for this to fail

yjqiang commented 5 years ago

I use the websocket in module “aiohttp” or “websockets” to connect websites. When the network is not stable. It shows this. I used "try except" for all the script, but it did not work.

jsbain commented 5 years ago

Did you have a minimal example that someone else could use to reproduce? Your previous example seemed very much linked to your own local network.

Do you get this error if, for example, you turn off WiFi/data? Or only when you have marginally stable connection? Is pythonista in the background when this fails?

jsbain commented 5 years ago

Again, we need a minimal example, not hundreds of lines of code.

Have you tested your code with a pc and the same server?

yjqiang commented 5 years ago

bug for pyista.zip About 150 lines. I just tested it. Is this clear now? (pythonista 320000, python 3.6.1, aiohttp 3.4.4)

jsbain commented 5 years ago

Not a pythonista problem. I reproduced your error on Android, when turning off data while the script ran.

I suspect you could duplicate on PC if you unplugged Ethernet, etc after the connection started.

yjqiang commented 5 years ago

I wrapped almost every network code with 'try'. And aiohttp's author said it is not a bug on aiohttp. Now it is not a bug in pythonista. ...I'm almost crying.

yjqiang commented 5 years ago

Can you help me to debug? I have been suffering from it for a long time.

jsbain commented 5 years ago

https://github.com/python/asyncio/issues/135

A search for the error would have resulted in this documented behavior in asyncio.

jsbain commented 5 years ago

https://github.com/python/asyncio/issues/80 Solution seems to be a custom error hndler to silence the warning.

jsbain commented 5 years ago

Or handle connection_lost, and don't worry about the extra logged warning

yjqiang commented 5 years ago

I wrapped all function using aiohttp with "try". But it kept showing this. And it seems it is a feature in asyncio instead of a bug?

yjqiang commented 5 years ago

I just don't know the reason why it shows this. Because when the connection is broken in low level like tcp, python should resend the msg itself. If the connection is broken for http connection, I used 'try' to catch it. So where is this bug coming from?

yjqiang commented 5 years ago

Or maybe aiohttp used asyncio to make a connection but aiohttp didn't handle this error?

cclauss commented 5 years ago

Correct. That is why there is the suggestion that install a custom error handler.

Your try / except is not working because it is not your code that is raising. Instead, it is code in the aio event loop that is raising so the custom error handler should be the right path forward.

yjqiang commented 5 years ago

Maybe aiohttp should handle it instead of me? I don't think user should handle timeout error in this way. And it is so strange since aiohttp also has aiohttp.ServerTimeoutError which is Derived from ServerConnectionError and asyncio.TimeoutError. What is the differnce between aiohttp.ServerTimeoutError and this "timout"?

jsbain commented 5 years ago

This error occurs when the server closes the connection unexpectedly or otherwise you are disconnected. The error is logged, but calls connection_lost on the Transport or Protocol. So if you want to handle the actual problem so you can retry, then implement a connection_lost handler. But if you want to turn off logging, you need the custom error_handler.

This is coming from asyncio, not aiohttp or anywhere else.

yjqiang commented 5 years ago

But why it shows? If the network is not good, python can wait until I read the msg from it, and then it raises this error. It just shows in the background and I have to catch it out of the connection.

And before this, I didn't catch the error, it seems just annoying but I didn't find anything, the connection of aiohttp didn't lost. What should I do to this error? Just ignore it?

yjqiang commented 5 years ago

def _fatal_error(self, exc, message='Fatal error on transport'):
        # Should be called from exception handler only.
        if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
            if self._loop.get_debug():
                logger.debug("%r: %s", self, message, exc_info=True)
        else:
            self._loop.call_exception_handler({
                'message': message,
                'exception': exc,
                'transport': self,
                'protocol': self._protocol,
            })
        self._force_close(exc)

_FATAL_ERROR_IGNORE = (BrokenPipeError,
                       ConnectionResetError, ConnectionAbortedError)
yjqiang commented 5 years ago

I read the code of asyncio, timeout doesn't belong to fatal_error_ignore. So I think I should just ignore it. But it is so strange since timeout does not belong to fatal_error_ignore.

jsbain commented 5 years ago

try this:

from asyncio import constants
constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES = 1000000  # some big number

The "error" you see is just a logging of an exception that ultimately will result in a different event that your code is handling.

jsbain commented 5 years ago

Actually, it looks like if you don't want the exception handler called, you can add to _FATAL_ERROR_IGNORE: asyncio.base_events._FATAL_ERROR_IGNORE.append(TimeoutError)

Maybe go ahead and close the various issues you have open on this topic?

yjqiang commented 5 years ago

Sorry, but I just dont know why asyncio did not just ignore it as others. So I'm asking the author of aiohttp.

yjqiang commented 5 years ago

And I just keep one issue open here for this problem. Where are the others?

cclauss commented 5 years ago

https://github.com/omz/Pythonista-Issues/issues/created_by/yjqiang

yjqiang commented 5 years ago

I still didn't find the answers to these questions. And these are not the same question.

yjqiang commented 5 years ago

By the way, _FALTAL_ERROR_IGNORE is 'tuple' so we can't use append.

jsbain commented 5 years ago

Your questions are not related to pythonista. I'd suggest stackoverflow or general aiohttp/asyncio questions.

Re fatal error ignore, you are right about it being a tuple. You would use asyncio._FATAL_ERROR_IGNORE += (TimeoutError,) to append to it.

yjqiang commented 5 years ago

Sorry. Thx a lot for this. Sorry to bother you for a long time. Thank you.