0

I'm using the whatismyip package to check my IP address before I call an IP sensitive API. The code runs in a loop and I'm finding after a few iterations I get the following error:

OSError: [Errno 48] Address already in use

From some searching I understand this is because whatismyip is trying to use its designated port before it's been freed up.

I've tried creating an MRE to replicate the error:

import time
import whatismyip

EXPECTED_IP = "123.123.123.123"

while True:
    current_ip_address = whatismyip.whatismyipv4()
    if current_ip_address != EXPECTED_IP:
        raise Exception
    time.sleep(0.1) # simulate accessing IP sensitive API for info A
    current_ip_address = whatismyip.whatismyipv4()
    if current_ip_address != EXPECTED_IP:
        raise Exception
    time.sleep(0.1) # simulate accessing IP sensitive API for info B
    current_ip_address = whatismyip.whatismyipv4()
    if current_ip_address != EXPECTED_IP:
        raise Exception
    time.sleep(0.1) # simulate accessing IP sensitive API for info C

However, annoyingly it only spits out:

ResourceWarning: unclosed <socket.socket fd=73, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('0.0.0.0', 54320)>

This looks related to my error but doesn't stop the code.

In the real code I've tried catching the OSError and retrying whatismyip.whatismyipv4() but this just generates the same error.

The error occurs on the last line of this block of code that I've extracted from the package:

SOURCE_IP = '0.0.0.0'
SOURCE_PORT = 54320

sockObj = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sockObj.settimeout(2)
sockObj.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sockObj.bind((SOURCE_IP, SOURCE_PORT))

In searching for solutions, most answers, e.g. this one, seem to recommend finding the process that uses the port and kill it. However, these don't provide any code I could include in my script. In addition to this I came across this post which says you can't get the OS to close a socket. It then recommends implementing the same code that's already above:

sockObj.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

I realise this isn't a perfect post because I can't replicate the error in an MRE but would anyone have any ideas how to solve this?

I'm using python 3.10.8 on MacOS 13.2.1.

Jossy
  • 589
  • 2
  • 12
  • 36
  • If you're getting that error when you simply call the library function in a loop, it's a bug in the library. – Barmar May 05 '23 at 20:34
  • Please show the full traceback of the error. – Barmar May 05 '23 at 20:35
  • It looks like MacOS implements `SO_REUSEADDR` on UDP sockets different from Linux. I suspect they only tested the code on Linux. – Barmar May 05 '23 at 20:43
  • Hi. Thanks for responding. Looks like you've found the issue. Here's a link to a post that explains more fully: https://stackoverflow.com/questions/51998042/macos-so-reuseaddr-so-reuseport-not-consistent-with-linux. No solutions there though - any ideas? – Jossy May 05 '23 at 21:51
  • Report the problem to the `whatismyip` programmer – Barmar May 05 '23 at 21:56

0 Answers0