Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-blocking behaviour #28

Open
wurls80 opened this issue Sep 17, 2023 · 7 comments
Open

Non-blocking behaviour #28

wurls80 opened this issue Sep 17, 2023 · 7 comments

Comments

@wurls80
Copy link

wurls80 commented Sep 17, 2023

I was trying ampule to replace adafruit httpserver as have been seeing some issues with reliability.

I got the code working to host the html page and respond to button presses on that page - so long as running in blocking mode. However I need to run in non-blocking mode (I was polling the server instance formed with httpserver, as the hardware checks for a physical button press too).

I can't get the non-blocking examples to work - whenever I try to connect to the IP address I get:
"Error reading from socket [Errno 11] EAGAIN
Error with request: need more than 0 values to unpack"
And the device trying to connect to the IP address reports it can't connect and the connection is being reset. I see this same behaviour with my code as well when set socket.setblocking(False) too.

I've seen your advice in [(https://github.com//pull/26)] however I can't determine how to manually override the setting on the accept() socket (I assume this is what I need to do). I've tried setting the timeout on the socket created (i.e. the listening socket) that the accept socket should then inherit the timeout from, but it doesn't make any difference to the behaviour.

Any ideas why I can't get your non-blocking example to work? I'm using a pi pico running circuitpython 8.1.0.

Many thanks.

@deckerego
Copy link
Owner

@wurls80 - apologies for the delay in replying, GitHub evidently no longer feels I should be notified for open issues...

Does the blocking example work? It sounds to me like you already have an open socket or something else using the listening network interface - so my guess is that the blocking code will fail in the same way that the non-blocking one will.

If you have some sample code to share, happy to take a look.

@deckerego
Copy link
Owner

@wurls80 following up again, let me know if you have any code samples to share. Thanks!

@wurls80
Copy link
Author

wurls80 commented Nov 21, 2023 via email

@deckerego
Copy link
Owner

Sounds good - will close this for now, but happy to re-open later!

@szampardi
Copy link

hi @deckerego, I have stumbled into the same issue and am able to reproduce and help you investigate the issue which is still occurring on latest stable CircuitPython 9.0.5 running on a pi pico w. Here's the code:

import time
import board
import busio
from digitalio import DigitalInOut

gate = DigitalInOut(board.GP0)
gate.switch_to_output(value=True)
def open_gate():
	gate.value = False
	time.sleep(0.05)
	gate.value= True
	print('gate opened')

bell = DigitalInOut(board.GP1)
bell.switch_to_output(value=True)
def ring_bell(t: float = 1.0):
	bell.value = False
	time.sleep(t)
	bell.value = True
	print('rang bell')

import wifi
import socketpool
import ampule

headers = {
    "Content-Type": "application/json; charset=UTF-8",
    "Access-Control-Allow-Origin": '*',
    "Access-Control-Allow-Methods": 'GET, POST',
    "Access-Control-Allow-Headers": 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
}

@ampule.route("/open_gate")
def api_open_gate(request):
    try:
        open_gate()
        return (200, headers, '{"ok":true}')
    except Exception as e:
        print(e)

@ampule.route("/ring_bell")
def api_ring_bell(request):
    t = 1.0
    if (request.params is None) or (request.params["t"] is None):
        ring_bell(t)
        return (200, headers, '{"ok":true}')
    try:
        t = float(request.params["t"])
    except Exception as e:
        print(e)
        return (502, headers, '{"ok":false}')
    try:
        ring_bell(t)
        return (200, headers, '{"ok":true}')
    except Exception as e:
        print(e)
        return (500, headers, '{"ok":false}')

pool = socketpool.SocketPool(wifi.radio)
socket = pool.socket()
socket.setsockopt(pool.SOL_SOCKET, pool.SO_REUSEADDR, 1)
socket.bind(['0.0.0.0', 8000])
socket.listen(1)
socket.setblocking(False)
print("HTTP API starting on port 8000")
while True:
    print('socket listening')
    ampule.listen(socket)
    time.sleep(1)

few things probably worth noting:

  • I'm listening on port 8000 because 80 is already taken by the CircuitPython Web Workflow service, I should check if the same issue occurs when that is disabled;
  • I added socket.setsockopt(pool.SOL_SOCKET, pool.SO_REUSEADDR, 1) because otherwise subsequent soft reloads would fail to start, could that be the cause of the problem?

Regards,

@deckerego
Copy link
Owner

I would guess that the address re-use could cause the problem - it seems like you would have multiple resources competing for the same sockets. Do things work (until you have to soft reload) without those socket options?

@deckerego deckerego reopened this Jun 19, 2024
@szampardi
Copy link

Ok! Will try over the weekend and let you know

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants