Reputation: 587
I have a receiver which is listening for both TCP and UDP packets. I also have a foo() def that runs simultaneously and prints the current time and sends a UDP packet every 5 seconds.
The problem is that when I press Ctrl + C buttons in order to terminate the program, the first time it isn't terminated and I should press these buttons at least two times.
I added raise as it was suggested in this post. It worked me in the previous question, but after I added some other parts, it didn't work again.
Here is the code:
from __future__ import print_function
from select import select
import socket
from struct import pack
from struct import unpack
from collections import deque
host = '10.0.0.2'
port = 5005
backlog = 5
BUFSIZE = 4096
q = deque()
import time, threading
def foo():
try:
print(time.ctime())
threading.Timer(5, foo).start()
except KeyboardInterrupt:
print('\nClosing')
raise
class Receiver:
''' Buffer binary data from socket conn '''
def __init__(self, conn):
self.conn = conn
self.buff = bytearray()
def get(self, size):
''' Get size bytes from the buffer, reading
from conn when necessary
'''
while len(self.buff) < size:
data = self.conn.recv(BUFSIZE)
if not data:
break
self.buff.extend(data)
# Extract the desired bytes
result = self.buff[:size]
# and remove them from the buffer
del self.buff[:size]
return bytes(result)
def save(self, fname):
''' Save the remaining bytes to file fname '''
with open(fname, 'wb') as f:
if self.buff:
f.write(bytes(self.buff))
while True:
data = self.conn.recv(BUFSIZE)
if not data:
break
f.write(data)
def send(sock2, data2):
while data2:
sent = sock2.send(data2)
data2 = data2[sent:]
def send_file(ipToTransfer, fname):
with open(fname, 'rb') as f:
sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock2.connect((ipToTransfer, 5005))
except socket.error as err:
print(err, ipToTransfer, 5005)
sock2.close()
return
# Send the file name length & the filename itself in one packet
send(sock2, pack('B', len(fname)) + fname.encode())
while True:
data2 = f.read(BUFSIZE)
if not data2:
break
send(sock2, data2)
sock2.close()
def read_tcp(s):
conn, addr = s.accept()
print('Connected with', *addr)
# Create a buffer for this connection
receiver = Receiver(conn)
# Get the length of the file name
name_size = unpack('B', receiver.get(1))[0]
name = receiver.get(name_size).decode()
q.append(name)
print('name', name)
# Save the file
receiver.save(name)
conn.close()
print('saved\n')
def read_udp(s):
data,addr = s.recvfrom(1024)
print("received message:", data)
def run():
# create tcp socket
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
tcp.bind((host,port))
except socket.error as err:
print('Bind failed', err)
return
tcp.listen(1)
# create udp socket
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
udp.bind((host,port))
print('***Socket now listening at***:', host, port)
input = [tcp,udp]
try:
while True:
inputready,outputready,exceptready = select(input,[],[])
for s in inputready:
if s == tcp:
read_tcp(s)
elif s == udp:
read_udp(s)
else:
print("unknown socket:", s)
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
raise
tcp.close()
udp.close()
if __name__ == '__main__':
foo()
run()
The first time I press Ctrl + C
, the program is not terminated and I need to press them for the second time. What's wrong? How can i kill the program by pressing Ctrl + C
for the first time?
Upvotes: 2
Views: 1549
Reputation: 249053
How can i kill the program by pressing
Ctrl + C
for the first time?
An easy way is to remove the signal handler, and let the process die immediately on SIGINT. Put this near the beginning of your code:
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
Another option is that you can press Ctrl + \
to send SIGQUIT instead of SIGINT. That works with no code changes in most programs...but may generate core dumps.
Note that by doing either of the above, you rob the program of the ability to perform graceful shutdown. But this may not be important for most programs, as the operating system will clean up unused resources upon termination.
Upvotes: 2
Reputation: 1107
When you press ctrl + c
for the first time it terminates the thread that you are currently in, but it doesn't terminate the main thread where the rest of the program is running. When you do it for the second time you are terminating the main thread
Upvotes: 1