Home > Software engineering >  select() call still blocking after call to setblocking(False)
select() call still blocking after call to setblocking(False)

Time:03-20

I have this bit of server side code:

    def listen_on_port(self):

        try:
            running = True
            HOST = ''                # Symbolic name meaning all available interfaces
            PORT = int(self.port)    # Arbitrary non-privileged port
            server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            server_socket.bind((HOST, PORT))
            server_socket.listen()
            server_socket.setblocking(False)  # non-blocking I/O
            self.logger.info(f'listening on port {self.port}')
            read_list = [server_socket]
            while running:
               try:
                    self.logger.info(f'calling select().')
                    readable, writable, errored = select.select(read_list, [], [])
                    self.logger.info(f'called select().')
                    for s in readable:
                        if s is server_socket:
                            client_socket, address = server_socket.accept()
                            read_list.append(client_socket)
                            self.logger.info(f"Connection from address = {address} client_socket is {client_socket}.")
                        else:
                            self.logger.info(f"going to call s.recv(). s is {s}")
                            try:
                                data = s.recv(1024)
                                self.logger.info(f"Got data = {data}.")
                                if 'terminate' in data.decode('utf-8'):
                                    self.logger.info(f"terminating.")
                                    running = False
                            except Exception as ex:
                                self.logger.info(f'error s.recv() ex={ex}.')
                            finally:
                                self.logger.info(f"closing socket. s = {s}.")
                                s.close()
                                read_list.remove(s)
               except Exception as ex:
                   self.logger.info(f'Inside while True. error ex={ex}.')
                   raise ex
        except Exception as ex:
            self.logger.info(f'error ex={ex}.')

When I run my script I can see in my log file that my code waits for ...

readable, writable, errored = select.select(read_list, [], [])

... to return. My log file:

$ cat /tmp/test.log    
doing port 50050
listening on port 50050
calling select().

I am calling ...

server_socket.setblocking(False)  # non-blocking I/O

... but the code still blocks. I am running on a mac (not a Linux system) if that matters.

CodePudding user response:

select doesn't care whether the sockets are blocking or not. If you want to make a non-blocking select call, you need to specify a timeout value of 0:

readable, writable, errored = select.select(read_list, [], [], 0)

That said, it's not like your code has anything better to do than block. Specifying timeout=0 is just going to turn your while running loop into a busy-wait.

  • Related