Repository navigation
Crash when ussl wrapped socket is running as a coroutine (no easily reproducible testcase) #3297
Copy link
Copy link
Closed
Description
File "/Users/richard/.micropython/lib/uasyncio/core.py", line 128, in run_forever
File "/Users/richard/.micropython/lib/uasyncio/core.py", line 100, in run_forever
File "/Users/richard/.micropython/lib/uasyncio/__init__.py", line 34, in add_reader
TypeError: can't convert ussl to int
How to reproduce:
import usocket
from uasyncio import StreamReader, StreamWriter, coroutine, get_event_loop, sleep as sleepasyncio
import gc
import sys
class Response:
def __init__(self, f, content_length):
self.raw = f
self.encoding = "utf-8"
self._cached = None
self.content_length = content_length
def close(self):
if self.raw:
self.raw.close()
self.raw = None
self._cached = None
@property
def content(self):
if self._cached is None:
lines = ""
if self.content_length < 500:
lines = self.raw.read(self.content_length).decode("utf-8")
else:
while True:
yield
line = self.raw.readline()
if not line or line == b"\r\n" or line == b'':
break
if line:
lines += line.decode("utf-8")
# print(lines)
self.raw.close()
self.raw = None
self._cached = lines
return self._cached
@content.setter
def content(self, value):
self._cached = value
@property
def text(self):
return str(self.content, self.encoding)
def json(self):
import ujson
data = yield from self.content
return ujson.loads(data)
def request(method, url, data=None, json=None, headers={}, stream=None):
try:
proto, dummy, host, path = url.split("/", 3)
except ValueError:
proto, dummy, host = url.split("/", 2)
path = ""
if proto == "http:":
port = 80
elif proto == "https:":
import ussl
port = 443
else:
raise ValueError("Unsupported protocol: " + proto)
if ":" in host:
host, port = host.split(":", 1)
port = int(port)
print("host:", host)
print("port:", port)
gc.collect()
try:
ai = usocket.getaddrinfo(host, port)
addr = ai[0][-1]
s = usocket.socket()
s.connect(addr)
if proto == "https:":
s = ussl.wrap_socket(s)
(reader, writer) = StreamReader(s), StreamWriter(s, {})
gc.collect()
headers['Accept-Encoding'] = 'identity'
yield from writer.awrite(b"%s /%s HTTP/1.1\r\n" % (method, path))
if not "Host" in headers:
yield from writer.awrite(b"Host: %s\r\n" % host)
# Iterate over keys to avoid tuple alloc
for k in headers:
yield from writer.awrite(k)
yield from writer.awrite(b": ")
yield from writer.awrite(headers[k])
yield from writer.awrite(b"\r\n")
if json is not None:
assert data is None
import ujson
data = ujson.dumps(json)
if data:
yield from writer.awrite(b"Content-Length: %d\r\n" % len(data))
yield from writer.awrite(b"\r\n")
if data:
yield from writer.awrite(data)
writer.aclose()
l = yield from reader.readline()
content_length = None
protover, status, msg = l.split(None, 2)
status = int(status)
while True:
l = s.readline()
yield
if not l or l == b"\r\n" or l == b'':
break
if l.startswith(b"Transfer-Encoding:"):
if b"chunked" in l:
raise ValueError("Unsupported " + str(l))
elif l.startswith(b"Location:") and not 200 <= status <= 299:
raise NotImplementedError("Redirects not yet supported")
elif l.startswith(b'Content-Length:'):
content_length = int(l.split(None, 2)[1])
resp = Response(s, content_length)
resp.status_code = status
resp.reason = msg.rstrip()
except Exception as e:
sys.print_exception(e)
raise ValueError("Cannot receive data, check connection")
gc.collect()
return resp
def head(url, **kw):
return request("HEAD", url, **kw)
def get(url, **kw):
return request("GET", url, **kw)
def post(url, **kw):
return request("POST", url, **kw)
def put(url, **kw):
return request("PUT", url, **kw)
def patch(url, **kw):
return request("PATCH", url, **kw)
def delete(url, **kw):
return request("DELETE", url, **kw)
def get_json(url):
r = yield from get(url)
json_result = yield from r.json()
r.close()
return json_result
@coroutine
def client():
while True:
print("client:", "sleep 10 seconds")
try:
json_object = yield from get_json('https://triac-server.herokuapp.com/api/values')
# json_object = yield from get_json('http://ip.jsontest.com/')
print(json_object)
except Exception as e:
sys.print_exception(e)
print("unable to fetch data, check connection")
yield from sleepasyncio(5)
loop = get_event_loop()
loop.call_soon(client())
loop.run_forever()
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
pfalcon commentedon Sep 3, 2017
Please see https://www.chiark.greenend.org.uk/~sgtatham/bugs.html
robert-hh commentedon Sep 3, 2017
That's a very good essay, a pleasure to read.
richarddd commentedon Sep 6, 2017
@robert-hh @pfalcon nice read! See updated issue 🥇 👍
pfalcon commentedon Nov 3, 2017
As far as I can tell, this issue is covered by #3394 . I'm thus closing this.
Merge pull request micropython#3297 from simmel-project/i2c