-
Notifications
You must be signed in to change notification settings - Fork 218
Write to nonblocking sockets fails #166
Comments
Looking into this ... |
Why not check for EINPROGRESS when attempting to write? Code below works for me import network
import socket
from time import sleep
import uerrno
SERVER = '192.168.0.9' # can use 'iot.eclipse.org'
SERVER = 'iot.eclipse.org'
s = network.WLAN(network.STA_IF)
s.active(True)
def connect():
s.disconnect()
sleep(1)
s.connect('SSID', 'PASSWORD') # Redacted EDIT this
print('Awaiting conection')
while not s.isconnected():
sleep(1)
print('Got conection, pausing') # Just to make sure
sleep(3)
print('conection done')
def foo(n):
print('Attempt:', n)
connect()
addr = socket.getaddrinfo(SERVER, 1883)[0][-1] # MQTT
s = socket.socket()
s.setblocking(False)
try:
s.connect(addr)
except OSError as e:
if e.args[0] not in [uerrno.EINPROGRESS, uerrno.ETIMEDOUT]:
print('Error connecting', e)
return
attempts = 3
while attempts:
attempts -= 1
try:
s.write(b"\xc0\0") # MQTT ping
print('Write succesful.')
break
except OSError as e:
if e.args[0] not in [uerrno.EINPROGRESS, uerrno.ETIMEDOUT]:
print('**** ERROR writing ****', e)
sleep(.5)
s.close()
foo(1) |
Here it works only by ignoring the 119 error and trying again. I've never seen the ESP8266 raise 119 and I'm not sure of its significance - perhaps you could advise. Is it always legitimate to trap it and re-send the entire buffer (which in the general case might be long)? Running your code with only the WiFi credentials changed:
|
The ESP8266 and ESP32 use two different versions of LWIP (ESP8266 version is from 2012, ESP32 from 2016). The ESP8266 version should throw an |
Which I'd understand if it threw Throwing an exception on I performed a quick test where I trapped the 119, including tests of writing a longer string. It seems that it only fails on the first pass. The second pass correctly writes the string. So perhaps this boils down to the LWIP raising a "wrong" exception number in the event of a pending |
I turned some debugging on ... lwip_send is getting error -5 back from netconn_write_partly and then translating that to EINPROGRESS. The trouble is that EINPROGRESS isn't consistently defined:
LWIP seems to be picking up on 119 definition, whereas lwip would normally define it as 115 and that's what py/mperrno.h things too ... |
Nice digging! There's already code in esp32/modsocket.c to convert EINPROGRESS to MP_EINPROGRESS, so the fix should be to make sure that the EINPROGRESS in that file is the same one that lwip uses. It's strange that the newlib errno.h is being used though.... how is that happening, is it on purpose? |
I should add that I've also seen 118 in my testing. My code treats EINPROGRESS, ETIMEDOUT, 118 and 119 as indicating that the connection is not yet established. So far it seems reliable. |
Yeah, I didn't quite get to the bottom of it but there's a |
Because some toolchains use non-standard errno codes and in the past was confusing that some ports would report certain error numbers, while others would report other numbers for the same thing. It was decided to standardise around one set of errno codes so that it was easier to work out what the code corresponded to (for those codes that don't have a human-readable string associated with them in the uerrno module). |
In the course of updating this asynchronous MQTT driver I want to make it compatible with ESP32. The code uses a nonblocking socket. I get OSError 119 when writing to the socket. The following test runs on ESP8266 but fails on ESP32.
Note that I issue disconnect() before connecting. This is because my driver reconnects after a network outage. It also ensures consistent behaviour if an application is started with a network connection already active.
The text was updated successfully, but these errors were encountered: