0
$ nslookup 192.168.85.242

runs for about 20 seconds and fails. Sending SIGINT (control-C) at any time during that 20 seconds causes the command to end instantly.

On the other hand, with Python 3.6.4:

$ python
Python 3.6.4 (default, Jan 26 2018, 08:18:54)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-18)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> socket.gethostbyaddr("192.168.85.242")
^C

Hitting control-C does nothing, the socket command seems determined not to give up.

My question is, why? And most importantly, if I'm looping through multiple IP addresses and I'd like my code to fail after, say 2 seconds, the standard ways of implementing a timeout (such as https://pypi.org/project/timeout-decorator/ and Timeout on a function call) won't work.

jsf80238
  • 1,577
  • 2
  • 11
  • 24

2 Answers2

0

Try Ctrl + \ which will issue a SIGQUIT instead of SIGINT. It tends to kill processes when CTRL + C fails.

Avindra Goolcharan
  • 4,032
  • 3
  • 41
  • 39
0

I ended up doing this, for some reason the multiprocessing module has the "power" to timeout the gethostbyaddr() method.

@functools.lru_cache(maxsize=None)
def gethostbyaddr(ip_address):
    try:
        base.get_logger().debug(f"Looking up {ip_address} ...")
        hostname, _, _ = socket.gethostbyaddr(ip_address)
        return hostname
    except (Exception, ) as e:
        base.get_logger().debug(str(e) + " for " + ip_address)
        return None

# We need this pool/multiprocessing business so as to timeout after a couple of seconds
# if we are not going to get an answer
# See https://docs.python.org/3/library/multiprocessing.html#using-a-pool-of-workers
@functools.lru_cache(maxsize=None)
def get_host_name(ip_address):
    with multiprocessing.Pool(processes=1) as pool:
        try:
            result = pool.apply_async(gethostbyaddr, (ip_address, ))
            return result.get(timeout=2)
        except multiprocessing.context.TimeoutError:
            return None

And in my main code I have:

entry_dict[defs.DNS] = get_host_name(row[defs.IP])
jsf80238
  • 1,577
  • 2
  • 11
  • 24