socket settimeout problem.

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
nedoskiv
Posts: 20
Joined: Fri Jan 18, 2019 10:48 am

socket settimeout problem.

Post by nedoskiv » Wed Jul 27, 2022 6:54 am

Hello,
I'm writing a simple wget script, but when try to connect to non existing IP or device that is offline, sock.connect take too long to rease an error

Code: Select all

>>> import usocket as socket
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sock.settimeout(2)
>>> sock.connect(("192.168.4.2",80))		// take more than 15 seconds
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 113] ECONNABORTED
Wondering am I doing something wrong or it just not work properly.
(tested on micropython version 1.19.1 and 1.18 - same result)
Last edited by nedoskiv on Wed Jul 27, 2022 7:25 am, edited 1 time in total.

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: socket settimeout problem.

Post by davef » Wed Jul 27, 2022 7:19 am

Something to try:

Code: Select all

import usocket

sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM)
send_data = b'I am going to listen for 5 seconds'
sock.settimeout(5) #  this sets the listening time
Works for me. Maybe try usocket then DGRAM might narrow the problem down.

nedoskiv
Posts: 20
Joined: Fri Jan 18, 2019 10:48 am

Re: socket settimeout problem.

Post by nedoskiv » Wed Jul 27, 2022 7:40 am

davef wrote:
Wed Jul 27, 2022 7:19 am
Something to try:

Code: Select all

import usocket

sock = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM)
send_data = b'I am going to listen for 5 seconds'
sock.settimeout(5) #  this sets the listening time
Works for me. Maybe try usocket then DGRAM might narrow the problem down.
I'm actually using usocket (just updated original post)

and I do not want to listten on socket, I want to connect

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: socket settimeout problem.

Post by davef » Wed Jul 27, 2022 8:10 am

I have never connected to a socket.

The next line in my script is:

Code: Select all

sent = sock.sendto(send_data, server_address)
I guess if server_address ('192.168.8.8', 10000) wasn't really there I might find the settimeout didn't apply there as well.

Hope someone else has the correct answer for you.

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: socket settimeout problem.

Post by davef » Wed Jul 27, 2022 8:57 am

Had to have a bit of a search:
https://stackoverflow.com/questions/343 ... on-timeout
maybe setdefaulttimeout(2.0)

nedoskiv
Posts: 20
Joined: Fri Jan 18, 2019 10:48 am

Re: socket settimeout problem.

Post by nedoskiv » Wed Jul 27, 2022 11:34 am

davef wrote:
Wed Jul 27, 2022 8:57 am
Had to have a bit of a search:
https://stackoverflow.com/questions/343 ... on-timeout
maybe setdefaulttimeout(2.0)

Code: Select all

>>> help (socket)
object <module 'usocket'> is of type module
  __name__ -- usocket
  __init__ -- <function>
  socket -- <class 'socket'>
  getaddrinfo -- <function>
  AF_INET -- 2
  AF_INET6 -- 10
  SOCK_STREAM -- 1
  SOCK_DGRAM -- 2
  SOCK_RAW -- 3
  IPPROTO_TCP -- 6
  IPPROTO_UDP -- 17
  IPPROTO_IP -- 0
  SOL_SOCKET -- 4095
  SO_REUSEADDR -- 4
  IP_ADD_MEMBERSHIP -- 3
there is no function about that in micropython
reading docs/discussions about sockets in python instead of micropython do not help

Anyway I found that this is known issue (on github) and is not yet fixed

https://github.com/micropython/micropython/issues/8326

marcidy
Posts: 133
Joined: Sat Dec 12, 2020 11:07 pm

Re: socket settimeout problem.

Post by marcidy » Wed Jul 27, 2022 1:56 pm

Try this example as-is:
https://github.com/micropython/micropyt ... _client.py

There's so much that can go wrong with local networking, are you 100% sure you are routing correctly, and everything happening on the address is correct?

User avatar
karfas
Posts: 193
Joined: Sat Jan 16, 2021 12:53 pm
Location: Vienna, Austria

Re: socket settimeout problem.

Post by karfas » Wed Jul 27, 2022 2:24 pm

marcidy wrote:
Wed Jul 27, 2022 1:56 pm
There's so much that can go wrong with local networking, are you 100% sure you are routing correctly, and everything happening on the address is correct?
@marcidy: The problem here is the duration of connect() when trying to reach an non-existing host.
A few hours of debugging might save you from minutes of reading the documentation! :D
My repositories: https://github.com/karfas

marcidy
Posts: 133
Joined: Sat Dec 12, 2020 11:07 pm

Re: socket settimeout problem.

Post by marcidy » Wed Jul 27, 2022 4:09 pm

karfas wrote:
Wed Jul 27, 2022 2:24 pm
marcidy wrote:
Wed Jul 27, 2022 1:56 pm
There's so much that can go wrong with local networking, are you 100% sure you are routing correctly, and everything happening on the address is correct?
@marcidy: The problem here is the duration of connect() when trying to reach an non-existing host.
ha, missed that, thanks for clarifying

marcidy
Posts: 133
Joined: Sat Dec 12, 2020 11:07 pm

Re: socket settimeout problem.

Post by marcidy » Fri Jul 29, 2022 11:15 pm

I intended to look more into this, but so far haven't been able to pick up the debugger and get at it.

I don't see anything raised on github for this, which i think is appropriate in this case. The issue is definitely at the C code level *somewhere*.

The connect method is fairly transparent:

Code: Select all

STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) {
    socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
    struct addrinfo *res;
    _socket_getaddrinfo(arg1, &res);
    MP_THREAD_GIL_EXIT();
    self->state = SOCKET_STATE_CONNECTED;
    int r = lwip_connect(self->fd, res->ai_addr, res->ai_addrlen);
    MP_THREAD_GIL_ENTER();
    lwip_freeaddrinfo(res);
    if (r != 0) {
        mp_raise_OSError(errno);
    }

    return mp_const_none;
}

The only two functions that are doing anything interesting are:

Code: Select all

    // ...
    _socket_getaddrinfo(arg1, &res);
    // ...
    int r = lwip_connect(self->fd, res->ai_addr, res->ai_addrlen);
    // ...
the getaddrinfo family of functions in that file result in blocking calls into the lwip library, and would be my first SWAG at where the problem is.

I don't yet know why "socket.connect" requires calling getaddrinfo, given that socket.conect is called with the results of calling socket.getaddrinfo(...) in python. I also haven't traced into lwip_connect enough to know if there's an issue there. Previously, i have traced the getaddrinfo calls down to the reasons they block, so im familiar with that code path.

So, really, a bunch of not-too-helpful information which says "raise it on github". I'd like to spend more time on it but i won't be able to do that until deep into next week at the earliest.

Post Reply