How do you catch getaddrinfo() errors

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

How do you catch getaddrinfo() errors

Post by davef » Sat Apr 17, 2021 10:47 pm

Sometimes getaddrinfo() doesn't work in a uMail application I run. This test script will run, expected output is <None> for random numbers of times before it fails ... with no error messages being displayed. I see fails in 3 - 20 calls , so I am hoping that every once in awhile it will fail on the first call! I run this on a ESP32 using the latest stable firmware.

Code: Select all

import usocket as socket
import utime
from socket import AF_INET, SOCK_STREAM


while True:

    s = socket.socket(AF_INET, SOCK_STREAM)

    try:
     #  Guaranteed to return an address which can be
     #  connected to for stream operation.
        address = s.connect(socket.getaddrinfo('smtp.gmail.com', 465, 0, SOCK_STREAM)[0][-1])
        print(address)
    except OSError as error:
        pass

    s.close()
    utime.sleep(1)
I have tried printing out error rather than pass in except OSError as error.

Could someone tell me how to properly catch what getaddrinfo() is choking-on and/or run the script and tell me what happens on your ESP32.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: How do you catch getaddrinfo() errors

Post by pythoncoder » Sun Apr 18, 2021 12:46 pm

DNS queries can be expected sometimes to fail. The reason no error message is displayed is because you are trapping the resultant OSError and ignoring it.

If you are always accessing the same IP address (or small set of addresses), you could do the DNS query/queries when the application starts (repeating on failure), and cache the result. That way you don't need to worry about runtime errors.
Peter Hinch
Index to my micropython libraries.

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

Re: How do you catch getaddrinfo() errors

Post by davef » Sun Apr 18, 2021 10:13 pm

At one stage I was displaying the error:

Code: Select all

error: -202
but don't how to handle it.

What seems to happens is that after displaying the error the machine just freezes. Can one stop OS system errors from freezing the ESP32? I suspect there is quite a bit I don't know about system errors and how to recovery gracefully from them.

Any suggested reading topics are appreciated.
Found this:
https://micropython-usermod.readthedocs ... ds_07.html
but still not sure if I would need to go through this hoop.

Thanks,
Dave

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

Re: How do you catch getaddrinfo() errors

Post by davef » Mon Apr 19, 2021 7:40 am

Hi Peter,

Working with your suggestion of checking that Gmail's SMTP server is accessible I am going to try this:

Code: Select all

import usocket as socket
from socket import AF_INET, SOCK_STREAM
import utime
import machine


def check_address():

    s = socket.socket(AF_INET, SOCK_STREAM)
    s.settimeout(120)    
    count = 0


    while (count < 10):
        count +=1

        try:
         #  Guaranteed to return an address which can be
         #  connected to for stream operation.
            address = s.connect(socket.getaddrinfo('smtp.gmail.com', 465, 0, SOCK_STREAM)[0][-1])
            print(address)

            if (address == None):
                break
            
        except OSError as error:
            pass

        utime.sleep(5) # settimeout(120)    

    s.close()

    if (count == 10):
        count = 0

        try:
            with open('errors.txt', 'a') as outfile:
                outfile.write('did NOT connect to Gmail' + '\n')
        except OSError:
            print('oops')

        machine.reset()

    print('ready to go')
Thanks for the hint.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: How do you catch getaddrinfo() errors

Post by pythoncoder » Mon Apr 19, 2021 8:55 am

Hi Dave,
that link is for writers of C modules. Python error handling is simple and you seem to be doing it correctly. I can't see why the machine is freezing: what happens if you interrupt the program with ctrl-c? This should produce a traceback to show what it was doing when interrupted.

There are two cases where errors occur. Connection to your DNS server via getaddrinfo and subsequent connection to gmail. Since gmail's IP address is not going to change, you can retrieve its address details after power up. Then store the result from getaddrinfo. This reduces the risk of problems each time you access gmail since you aren't reliant on a successful connection to your DNS serever.
Peter Hinch
Index to my micropython libraries.

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

Re: How do you catch getaddrinfo() errors

Post by davef » Mon Apr 19, 2021 9:39 am

OK on it being for C writers.

The device is freezing if left unattended. I think these might the "random events" that I have heard mentioned before for the ESP32. A software WDT recovers that situation, but because my data file is on ramdisk I currently lose it. I could save it before trying to send, which gives me the opportunity to manually get the file off the device at a later time.

I repeatedly checked Gmail's SMPT server address and I am sure I saw it change a few times over a 10-15 minute period. I will check that again as your solution sounds like it would be more robust.

That didn't take long ... took about 10 minutes for it to change from ('74.125.200.108', 465) to ('74.125.68.109', 465)

Thanks again for the tips.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: How do you catch getaddrinfo() errors

Post by pythoncoder » Mon Apr 19, 2021 3:49 pm

davef wrote:
Mon Apr 19, 2021 9:39 am
...
That didn't take long ... took about 10 minutes for it to change from ('74.125.200.108', 465) to ('74.125.68.109', 465)...
That's interesting. I wonder if the old address still worked? I'm no expert on this stuff but it's possible that Google maintain a pool of IP addresses and DNS servers serve up a random choice. If this is the case, my suggestion would work.

Both addresses respond to pings.
Peter Hinch
Index to my micropython libraries.

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

Re: How do you catch getaddrinfo() errors

Post by davef » Mon Apr 19, 2021 7:36 pm

Based my comment on:
https://www.sourceonetechnology.com/gma ... ss-ranges/
Yes, that’s a lot of different address ranges, and it’s likely that these Gmail IP address ranges will change over time and in the future,
"change over time" is rather imprecise.

As I get a new ntptime each day I might consider getting a current Gmail SMTP IP and saving it like you suggested earlier.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: How do you catch getaddrinfo() errors

Post by pythoncoder » Tue Apr 20, 2021 10:20 am

Interesting link. It's noteworthy that your two addresses both fall in the 74.125.0.0/16 range reported in September 2017. The article talks of the address ranges changing with time - it doesn't mention whether individual addresses within a range might become unavailable.

A possible approach to minimising DNS lookups might be to cache an address and only repeat the DNS lookup on failure when you attempt to use it. Or test the address by pinging it before use.
Peter Hinch
Index to my micropython libraries.

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

Re: How do you catch getaddrinfo() errors

Post by davef » Tue Apr 20, 2021 11:06 am

On the RaspberryPi application that I am porting to the ESP devices I would ping 8.8.8.8 to ensure at least the internet was available.

I'll will consider your suggestions to make more appropriate tests for the smtp.gmail.com server.

Thanks,
Dave

Post Reply