Browse Source

fix memory leak

akkariiin/master
AkaneAkaza 7 years ago
parent
commit
6ebd86fa48
  1. 12
      shadowsocks/crypto/openssl.py
  2. 2
      shadowsocks/crypto/sodium.py
  3. 6
      shadowsocks/crypto/table.py
  4. 12
      shadowsocks/encrypt.py
  5. 6
      shadowsocks/tcprelay.py

12
shadowsocks/crypto/openssl.py

@ -30,9 +30,11 @@ loaded = False
buf_size = 2048
ctx_cleanup = None
def load_openssl():
global loaded, libcrypto, buf
global loaded, libcrypto, buf, ctx_cleanup
libcrypto = util.find_library(('crypto', 'eay32'),
'EVP_get_cipherbyname',
@ -51,8 +53,10 @@ def load_openssl():
if hasattr(libcrypto, "EVP_CIPHER_CTX_cleanup"):
libcrypto.EVP_CIPHER_CTX_cleanup.argtypes = (c_void_p,)
ctx_cleanup = libcrypto.EVP_CIPHER_CTX_cleanup
else:
libcrypto.EVP_CIPHER_CTX_reset.argtypes = (c_void_p,)
ctx_cleanup = libcrypto.EVP_CIPHER_CTX_reset
libcrypto.EVP_CIPHER_CTX_free.argtypes = (c_void_p,)
libcrypto.RAND_bytes.restype = c_int
@ -120,11 +124,9 @@ class OpenSSLCrypto(object):
def clean(self):
if self._ctx:
if hasattr(libcrypto, "EVP_CIPHER_CTX_cleanup"):
libcrypto.EVP_CIPHER_CTX_cleanup(self._ctx)
else:
libcrypto.EVP_CIPHER_CTX_reset(self._ctx)
ctx_cleanup(self._ctx)
libcrypto.EVP_CIPHER_CTX_free(self._ctx)
self._ctx = None
ciphers = {

2
shadowsocks/crypto/sodium.py

@ -104,6 +104,8 @@ class SodiumCrypto(object):
# strip off the padding
return buf.raw[padding:padding + l]
def clean(self):
pass
ciphers = {
'salsa20': (32, 8, SodiumCrypto),

6
shadowsocks/crypto/table.py

@ -65,6 +65,9 @@ class TableCipher(object):
else:
return translate(data, self._decrypt_table)
def clean(self):
pass
class NoneCipher(object):
def __init__(self, cipher_name, key, iv, op):
pass
@ -72,6 +75,9 @@ class NoneCipher(object):
def update(self, data):
return data
def clean(self):
pass
ciphers = {
'none': (16, 0, NoneCipher),
'table': (16, 0, TableCipher)

12
shadowsocks/encrypt.py

@ -22,7 +22,7 @@ import sys
import hashlib
import logging
from shadowsocks import common
from shadowsocks import common, lru_cache
from shadowsocks.crypto import rc4_md5, openssl, sodium, table
@ -39,7 +39,7 @@ def random_string(length):
except NotImplementedError as e:
return openssl.rand_bytes(length)
cached_keys = {}
cached_keys = lru_cache.LRUCache(timeout=180)
def try_cipher(key, method=None):
@ -49,8 +49,6 @@ def try_cipher(key, method=None):
def EVP_BytesToKey(password, key_len, iv_len):
# equivalent to OpenSSL's EVP_BytesToKey() with count 1
# so that we make the same key and iv as nodejs version
if hasattr(password, 'encode'):
password = password.encode('utf-8')
cached_key = '%s-%d-%d' % (password, key_len, iv_len)
r = cached_keys.get(cached_key, None)
if r:
@ -69,6 +67,7 @@ def EVP_BytesToKey(password, key_len, iv_len):
key = ms[:key_len]
iv = ms[key_len:key_len + iv_len]
cached_keys[cached_key] = (key, iv)
cached_keys.sweep()
return key, iv
@ -146,6 +145,11 @@ class Encryptor(object):
else:
return b''
def dispose(self):
if self.decipher is not None:
self.decipher.clean()
self.decipher = None
def encrypt_all(password, method, op, data):
result = []
method = method.lower()

6
shadowsocks/tcprelay.py

@ -1162,6 +1162,8 @@ class TCPRelayHandler(object):
if self._protocol:
self._protocol.dispose()
self._protocol = None
self._encryptor.dispose()
self._encryptor = None
self._dns_resolver.remove_callback(self._handle_dns_resolved)
self._server.remove_handler(self)
@ -1169,6 +1171,10 @@ class TCPRelayHandler(object):
self._server.add_connection(-1)
self._server.stat_add(self._client_address[0], -1)
#import gc
#gc.collect()
#logging.debug("gc %s" % (gc.garbage,))
class TCPRelay(object):
def __init__(self, config, dns_resolver, is_local, stat_callback=None, stat_counter=None):
self._config = config

Loading…
Cancel
Save