Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
203 views
in Technique[技术] by (71.8m points)

c++ linux accept() blocking after socket closed

I have a thread that listens for new connections

new_fd = accept(Listen_fd, (struct sockaddr *) & their_addr, &sin_size);

and another thread that closes Listen_fd when when it's time to close the program. After Listen_fd is closed however, it still blocks. When I use GDB to try and debug accept() doesn't block. I thought that it could be a problem with SO_LINGER, but it shouldn't be on by default, and shouldn't change when using GDB. Any idea whats going on, or any other suggestion to closing the listing socket?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Use: sock.shutdown (socket.SHUT_RD)

Then accept will return EINVAL. No ugly cross thread signals required!

From the Python documentation: "Note close() releases the resource associated with a connection but does not necessarily close the connection immediately. If you want to close the connection in a timely fashion, call shutdown() before close()."

http://docs.python.org/3/library/socket.html#socket.socket.close

I ran into this problem years ago, while programming in C. But I only found the solution today, after running into the same problem in Python, AND pondering using signals (yuck!), AND THEN remembering the note about shutdown!

As for the comments that say you should not close/use sockets across threads... in CPython the global interpreter lock should protect you (assuming you are using file objects rather than raw, integer file descriptors).

Here is example code:

import socket, threading, time

sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind (('', 8000))
sock.listen (5)

def child ():
  print ('child  accept ...')
  try:  sock.accept ()
  except OSError as exc :  print ('child  exception  %s' % exc)
  print ('child  exit')

threading.Thread ( target = child ).start ()

time.sleep (1)
print ('main   shutdown')
sock.shutdown (socket.SHUT_RD)

time.sleep (1)
print ('main   close')
sock.close ()

time.sleep (1)
print ('main   exit')

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...