Hello,
When you run this small code on Linux, the memory increases forever. Any idea why?
This code simply create 2 servers and exchange data between a client and the 2 servers like this:
client <=tcp=> forwarder server <=tcp=> echo server
The client send a random data to forwarder server that forward data to “echo server”, and the echo server send back received data. When client got back original data, he send again a new random data and so on forever.
If you comment/uncomment the BUFFER_SIZE at start of application, no more memory leak. Why?
Also seems to have same behaviour on any python version, including python2.
#!/usr/bin/env python3
import os
import time
import random
import struct
import socket
import threading
BUFFER_SIZE = 32768
#BUFFER_SIZE = 1048576
# Connect to a host
def connect(address, port):
handle = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
handle.settimeout(None)
handle.connect((address, port))
return handle
# Download data from socket
def download(host, size):
data = bytearray()
while size > 0:
buffer = host.recv(1048576)
if len(buffer) > 0:
data += buffer
size -= len(buffer)
else:
return None
return bytes(data)
# Run a new thread
def thread(target, args):
handle = threading.Thread(target=target, args=args)
handle.start()
return handle
# Exchange data
def exchange(local, remote):
while True:
remote.sendall(local.recv(BUFFER_SIZE))
# Data forwarder
def forwarder(local):
print("New forwarder client <=> forwarder <=> echo")
remote = connect("127.0.0.1", 22222)
thread(exchange, [local, remote])
thread(exchange, [remote, local])
# Echo
def echo(client):
print("New echo")
while True:
data = client.recv(4)
size = struct.unpack("!I", data)[0]
data = download(client, size)
if data:
client.sendall(data)
else:
break
# Client
def client(hostname, port, funder):
print("New client")
remote = connect("127.0.0.1", 11111)
while True:
size = random.randint(1, 4096 * 64)
data = os.urandom(size)
remote.sendall(struct.pack("!I", size) + data)
if data != download(remote, size):
print("Invalid echo")
# Server
def server(function, port):
print("Server binding on port {}".format(port))
handle = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
handle.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
handle.settimeout(None)
handle.bind(("127.0.0.1", port))
handle.listen(5)
while True:
thread(function, [handle.accept()[0]])
# Main
def main():
thread(server, [forwarder, 11111])
thread(server, [echo, 22222])
time.sleep(1)
for i in range(100):
thread(client, ["127.0.0.1", 22222, True])
while True:
time.sleep(1)
if __name__ == "__main__":
main()