[kimchi-devel][PATCH 0/7] Multiple instances of file handler leak fix

From: Royce Lv <lvroyce@linux.vnet.ibm.com> File handler leak can be tested with following scripts against real model kimchi server, run "lsof -p $(kimchidpid)" and you can see many file opened without close. import base64 import json import os import unittest import time from functools import partial from utils import request host = None ssl_port = None def setUpModule(): global host, ssl_port host = '127.0.0.1' ssl_port = 8001 class RestTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port) def test_leak(self): def fake_auth_header(): headers = {'Accept': 'application/json'} user, pw = ('my_username', 'my_passwd') hdr = "Basic " + base64.b64encode("%s:%s" % (user, pw)) headers['AUTHORIZATION'] = hdr return headers def do_thousands(url): for i in range(1000): self.request(url, headers=fake_auth_header()) print "called %i times" % i url = "https://%s:%s/toys" % \ (host, ssl_port) do_thousands(url) Royce Lv (7): Fix md5 file handler leak Fix file handler leak for uptime file Close json schema file after loading close fh after iso scanning Fix leak in check_url_path Work around eventfd leak using multiprocessing Fix file handler leak in netinfo.py src/kimchi/auth.py | 65 +++++++++++++++++++++++----------------- src/kimchi/isoinfo.py | 5 ++-- src/kimchi/model/debugreports.py | 5 ++-- src/kimchi/model/host.py | 5 ++-- src/kimchi/netinfo.py | 16 ++++++---- src/kimchi/root.py | 4 +-- src/kimchi/utils.py | 4 ++- 7 files changed, 61 insertions(+), 43 deletions(-) -- 1.9.3

From: Royce Lv <lvroyce@linux.vnet.ibm.com> md5 file open without close, fix by closing it in with clause. Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/model/debugreports.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/kimchi/model/debugreports.py b/src/kimchi/model/debugreports.py index fbc0463..222270d 100644 --- a/src/kimchi/model/debugreports.py +++ b/src/kimchi/model/debugreports.py @@ -112,8 +112,9 @@ class DebugReportsModel(object): # Deleting md5 msg = 'Deleting report md5 file: "%s"' % (md5_report_file) kimchi_log.info(msg) - md5 = open(md5_report_file).read().strip() - kimchi_log.info('Md5 file content: "%s"', md5) + with open(md5_report_file) as f: + md5 = f.read().strip() + kimchi_log.info('Md5 file content: "%s"', md5) os.remove(md5_report_file) cb('OK', True) return -- 1.9.3

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 20/01/2015 06:45, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
md5 file open without close, fix by closing it in with clause.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/model/debugreports.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/kimchi/model/debugreports.py b/src/kimchi/model/debugreports.py index fbc0463..222270d 100644 --- a/src/kimchi/model/debugreports.py +++ b/src/kimchi/model/debugreports.py @@ -112,8 +112,9 @@ class DebugReportsModel(object): # Deleting md5 msg = 'Deleting report md5 file: "%s"' % (md5_report_file) kimchi_log.info(msg) - md5 = open(md5_report_file).read().strip() - kimchi_log.info('Md5 file content: "%s"', md5) + with open(md5_report_file) as f: + md5 = f.read().strip() + kimchi_log.info('Md5 file content: "%s"', md5) os.remove(md5_report_file) cb('OK', True) return

From: Royce Lv <lvroyce@linux.vnet.ibm.com> Proc uptime file opened without close, close it in with clause. Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/model/host.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/kimchi/model/host.py b/src/kimchi/model/host.py index dff89cb..7f2ccdc 100644 --- a/src/kimchi/model/host.py +++ b/src/kimchi/model/host.py @@ -167,8 +167,9 @@ class HostStatsModel(object): # FIXME when we upgrade psutil, we can get uptime by psutil.uptime # we get uptime by float(open("/proc/uptime").readline().split()[0]) # and calculate the first io_rate after the OS started. - seconds = (timestamp - preTimeStamp if preTimeStamp else - float(open("/proc/uptime").readline().split()[0])) + with open("/proc/uptime") as time_f: + seconds = (timestamp - preTimeStamp if preTimeStamp else + float(time_f.readline().split()[0])) self.host_stats['timestamp'] = timestamp self._get_host_disk_io_rate(seconds) -- 1.9.3

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 20/01/2015 06:45, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Proc uptime file opened without close, close it in with clause.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/model/host.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/kimchi/model/host.py b/src/kimchi/model/host.py index dff89cb..7f2ccdc 100644 --- a/src/kimchi/model/host.py +++ b/src/kimchi/model/host.py @@ -167,8 +167,9 @@ class HostStatsModel(object): # FIXME when we upgrade psutil, we can get uptime by psutil.uptime # we get uptime by float(open("/proc/uptime").readline().split()[0]) # and calculate the first io_rate after the OS started. - seconds = (timestamp - preTimeStamp if preTimeStamp else - float(open("/proc/uptime").readline().split()[0])) + with open("/proc/uptime") as time_f: + seconds = (timestamp - preTimeStamp if preTimeStamp else + float(time_f.readline().split()[0]))
self.host_stats['timestamp'] = timestamp self._get_host_disk_io_rate(seconds)

From: Royce Lv <lvroyce@linux.vnet.ibm.com> Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/root.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kimchi/root.py b/src/kimchi/root.py index 6f191eb..eb0ade7 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -120,8 +120,8 @@ class KimchiRoot(Root): self.default_page = 'kimchi-ui.html' for ident, node in sub_nodes.items(): setattr(self, ident, node(model)) - self.api_schema = json.load(open(os.path.join(paths.src_dir, - 'API.json'))) + with open(os.path.join(paths.src_dir, 'API.json')) as f: + self.api_schema = json.load(f) self.paths = paths self.domain = 'kimchi' self.messages = messages -- 1.9.3

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 20/01/2015 06:45, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/root.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/kimchi/root.py b/src/kimchi/root.py index 6f191eb..eb0ade7 100644 --- a/src/kimchi/root.py +++ b/src/kimchi/root.py @@ -120,8 +120,8 @@ class KimchiRoot(Root): self.default_page = 'kimchi-ui.html' for ident, node in sub_nodes.items(): setattr(self, ident, node(model)) - self.api_schema = json.load(open(os.path.join(paths.src_dir, - 'API.json'))) + with open(os.path.join(paths.src_dir, 'API.json')) as f: + self.api_schema = json.load(f) self.paths = paths self.domain = 'kimchi' self.messages = messages

From: Royce Lv <lvroyce@linux.vnet.ibm.com> When check remote iso, we open an url without close it. fix this using contextlib. Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/isoinfo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/kimchi/isoinfo.py b/src/kimchi/isoinfo.py index fb87949..34e526c 100644 --- a/src/kimchi/isoinfo.py +++ b/src/kimchi/isoinfo.py @@ -17,6 +17,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +import contextlib import glob import platform import os @@ -414,8 +415,8 @@ lang=en#!/wiki/W51a7ffcf4dfd_4b40_9d82_446ebc23c550/page/PowerLinux\ request = urllib2.Request(self.path) range_header = "bytes=%d-%d" % (offset, offset + size - 1) request.add_header("range", range_header) - response = urllib2.urlopen(request) - data = response.read() + with contextlib.closing(urllib2.urlopen(request)) as response: + data = response.read() else: with open(self.path) as fd: fd.seek(offset) -- 1.9.3

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 20/01/2015 06:45, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
When check remote iso, we open an url without close it. fix this using contextlib.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/isoinfo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/kimchi/isoinfo.py b/src/kimchi/isoinfo.py index fb87949..34e526c 100644 --- a/src/kimchi/isoinfo.py +++ b/src/kimchi/isoinfo.py @@ -17,6 +17,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+import contextlib import glob import platform import os @@ -414,8 +415,8 @@ lang=en#!/wiki/W51a7ffcf4dfd_4b40_9d82_446ebc23c550/page/PowerLinux\ request = urllib2.Request(self.path) range_header = "bytes=%d-%d" % (offset, offset + size - 1) request.add_header("range", range_header) - response = urllib2.urlopen(request) - data = response.read() + with contextlib.closing(urllib2.urlopen(request)) as response: + data = response.read() else: with open(self.path) as fd: fd.seek(offset)

From: Royce Lv <lvroyce@linux.vnet.ibm.com> url opened without close, fix it with contextlib Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py index 6acfa42..a279bc0 100644 --- a/src/kimchi/utils.py +++ b/src/kimchi/utils.py @@ -19,6 +19,7 @@ # import cherrypy +import contextlib import grp import os import psutil @@ -147,7 +148,8 @@ def check_url_path(path): urlpath = parse_result.path if not urlpath: # Just a server, as with a repo. - code = urllib2.urlopen(path).getcode() + with contextlib.closing(urllib2.urlopen(path)) as res: + code = res.getcode() else: # socket.gaierror could be raised, # which is a child class of IOError -- 1.9.3

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 20/01/2015 06:45, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
url opened without close, fix it with contextlib
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py index 6acfa42..a279bc0 100644 --- a/src/kimchi/utils.py +++ b/src/kimchi/utils.py @@ -19,6 +19,7 @@ #
import cherrypy +import contextlib import grp import os import psutil @@ -147,7 +148,8 @@ def check_url_path(path): urlpath = parse_result.path if not urlpath: # Just a server, as with a repo. - code = urllib2.urlopen(path).getcode() + with contextlib.closing(urllib2.urlopen(path)) as res: + code = res.getcode() else: # socket.gaierror could be raised, # which is a child class of IOError

From: Royce Lv <lvroyce@linux.vnet.ibm.com> When accessing kimchi server url with authentication every time(no session), kimchi server will deny service after about 1000 requests. "GET /storagepools/default/storagevolumes/ HTTP/1.0" 200 563 "" "" Failed to run command: id -Gn royce. [Errno 24] Too many open files After tracking with 'lsof', "eventfd" handler leak for kimchi server. This is because when using pam_start() to generate a pam file handler, it needs to be closed by pam_end(). Unfortunately, PyPAM module only export start() function without end(). This patch workaround leak by putting PAM authentication in a sub process, so that when it finishes execution, its opening file handler will be closed by system automatically. REF: http://linux.die.net/man/3/pam_end http://stackoverflow.com/questions/5125245/how-to-authenticate-a-user-using-... Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/auth.py | 65 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py index 22c5c81..8cdbe76 100644 --- a/src/kimchi/auth.py +++ b/src/kimchi/auth.py @@ -145,35 +145,44 @@ class PAMUser(User): @staticmethod def authenticate(username, password, service="passwd"): '''Returns True if authenticate is OK via PAM.''' - def _pam_conv(auth, query_list, userData=None): - resp = [] - for i in range(len(query_list)): - query, qtype = query_list[i] - if qtype == PAM.PAM_PROMPT_ECHO_ON: - resp.append((username, 0)) - elif qtype == PAM.PAM_PROMPT_ECHO_OFF: - resp.append((password, 0)) - elif qtype == PAM.PAM_PROMPT_ERROR_MSG: - cherrypy.log.error_log.error( - "PAM authenticate prompt error: %s" % query) - resp.append(('', 0)) - elif qtype == PAM.PAM_PROMPT_TEXT_INFO: - resp.append(('', 0)) - else: - return None - return resp - - auth = PAM.pam() - auth.start(service) - auth.set_item(PAM.PAM_USER, username) - auth.set_item(PAM.PAM_CONV, _pam_conv) - try: - auth.authenticate() - except PAM.error, (resp, code): - msg_args = {'username': username, 'code': code} - raise OperationFailed("KCHAUTH0001E", msg_args) + def _auth(result): + def _pam_conv(auth, query_list, userData=None): + resp = [] + for i in range(len(query_list)): + query, qtype = query_list[i] + if qtype == PAM.PAM_PROMPT_ECHO_ON: + resp.append((username, 0)) + elif qtype == PAM.PAM_PROMPT_ECHO_OFF: + resp.append((password, 0)) + elif qtype == PAM.PAM_PROMPT_ERROR_MSG: + cherrypy.log.error_log.error( + "PAM authenticate prompt error: %s" % query) + resp.append(('', 0)) + elif qtype == PAM.PAM_PROMPT_TEXT_INFO: + resp.append(('', 0)) + else: + return None + return resp - return True + result.value = False + auth = PAM.pam() + auth.start(service) + auth.set_item(PAM.PAM_USER, username) + auth.set_item(PAM.PAM_CONV, _pam_conv) + try: + auth.authenticate() + except PAM.error, (resp, code): + msg_args = {'username': username, 'code': code} + raise OperationFailed("KCHAUTH0001E", msg_args) + + result.value = True + + result = multiprocessing.Value('i', 0, lock=False) + p = multiprocessing.Process(target=_auth, args=(result, )) + p.start() + p.join() + + return result.value class LDAPUser(User): -- 1.9.3

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 20/01/2015 06:45, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
When accessing kimchi server url with authentication every time(no session), kimchi server will deny service after about 1000 requests. "GET /storagepools/default/storagevolumes/ HTTP/1.0" 200 563 "" "" Failed to run command: id -Gn royce. [Errno 24] Too many open files After tracking with 'lsof', "eventfd" handler leak for kimchi server.
This is because when using pam_start() to generate a pam file handler, it needs to be closed by pam_end(). Unfortunately, PyPAM module only export start() function without end().
This patch workaround leak by putting PAM authentication in a sub process, so that when it finishes execution, its opening file handler will be closed by system automatically.
REF: http://linux.die.net/man/3/pam_end http://stackoverflow.com/questions/5125245/how-to-authenticate-a-user-using-...
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/auth.py | 65 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 28 deletions(-)
diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py index 22c5c81..8cdbe76 100644 --- a/src/kimchi/auth.py +++ b/src/kimchi/auth.py @@ -145,35 +145,44 @@ class PAMUser(User): @staticmethod def authenticate(username, password, service="passwd"): '''Returns True if authenticate is OK via PAM.''' - def _pam_conv(auth, query_list, userData=None): - resp = [] - for i in range(len(query_list)): - query, qtype = query_list[i] - if qtype == PAM.PAM_PROMPT_ECHO_ON: - resp.append((username, 0)) - elif qtype == PAM.PAM_PROMPT_ECHO_OFF: - resp.append((password, 0)) - elif qtype == PAM.PAM_PROMPT_ERROR_MSG: - cherrypy.log.error_log.error( - "PAM authenticate prompt error: %s" % query) - resp.append(('', 0)) - elif qtype == PAM.PAM_PROMPT_TEXT_INFO: - resp.append(('', 0)) - else: - return None - return resp - - auth = PAM.pam() - auth.start(service) - auth.set_item(PAM.PAM_USER, username) - auth.set_item(PAM.PAM_CONV, _pam_conv) - try: - auth.authenticate() - except PAM.error, (resp, code): - msg_args = {'username': username, 'code': code} - raise OperationFailed("KCHAUTH0001E", msg_args) + def _auth(result): + def _pam_conv(auth, query_list, userData=None): + resp = [] + for i in range(len(query_list)): + query, qtype = query_list[i] + if qtype == PAM.PAM_PROMPT_ECHO_ON: + resp.append((username, 0)) + elif qtype == PAM.PAM_PROMPT_ECHO_OFF: + resp.append((password, 0)) + elif qtype == PAM.PAM_PROMPT_ERROR_MSG: + cherrypy.log.error_log.error( + "PAM authenticate prompt error: %s" % query) + resp.append(('', 0)) + elif qtype == PAM.PAM_PROMPT_TEXT_INFO: + resp.append(('', 0)) + else: + return None + return resp
- return True + result.value = False + auth = PAM.pam() + auth.start(service) + auth.set_item(PAM.PAM_USER, username) + auth.set_item(PAM.PAM_CONV, _pam_conv) + try: + auth.authenticate() + except PAM.error, (resp, code): + msg_args = {'username': username, 'code': code} + raise OperationFailed("KCHAUTH0001E", msg_args) + + result.value = True + + result = multiprocessing.Value('i', 0, lock=False) + p = multiprocessing.Process(target=_auth, args=(result, )) + p.start() + p.join() + + return result.value
class LDAPUser(User):

From: Royce Lv <lvroyce@linux.vnet.ibm.com> Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/netinfo.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/kimchi/netinfo.py b/src/kimchi/netinfo.py index 991e91f..1cc4854 100644 --- a/src/kimchi/netinfo.py +++ b/src/kimchi/netinfo.py @@ -85,7 +85,9 @@ def all_interfaces(): def slaves(bonding): - return open(BONDING_SLAVES % bonding).readline().split() + with open(BONDING_SLAVES % bonding) as bonding_file: + res = bonding_file.readline().split() + return res def ports(bridge): @@ -108,7 +110,8 @@ def operstate(dev): def link_detected(dev): # try to read interface carrier (link) status try: - carrier = open(NET_STATE % dev).readline().strip() + with open(NET_STATE % dev) as dev_file: + carrier = dev_file.readline().strip() # when IOError is raised, interface is down except IOError: return "n/a" @@ -123,10 +126,11 @@ def get_vlan_device(vlan): dev = None if os.path.exists(PROC_NET_VLAN + vlan): - for line in open(PROC_NET_VLAN + vlan): - if "Device:" in line: - dummy, dev = line.split() - break + with open(PROC_NET_VLAN + vlan) as vlan_file: + for line in vlan_file: + if "Device:" in line: + dummy, dev = line.split() + break return dev -- 1.9.3

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 20/01/2015 06:45, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- src/kimchi/netinfo.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/src/kimchi/netinfo.py b/src/kimchi/netinfo.py index 991e91f..1cc4854 100644 --- a/src/kimchi/netinfo.py +++ b/src/kimchi/netinfo.py @@ -85,7 +85,9 @@ def all_interfaces():
def slaves(bonding): - return open(BONDING_SLAVES % bonding).readline().split() + with open(BONDING_SLAVES % bonding) as bonding_file: + res = bonding_file.readline().split() + return res
def ports(bridge): @@ -108,7 +110,8 @@ def operstate(dev): def link_detected(dev): # try to read interface carrier (link) status try: - carrier = open(NET_STATE % dev).readline().strip() + with open(NET_STATE % dev) as dev_file: + carrier = dev_file.readline().strip() # when IOError is raised, interface is down except IOError: return "n/a" @@ -123,10 +126,11 @@ def get_vlan_device(vlan): dev = None
if os.path.exists(PROC_NET_VLAN + vlan): - for line in open(PROC_NET_VLAN + vlan): - if "Device:" in line: - dummy, dev = line.split() - break + with open(PROC_NET_VLAN + vlan) as vlan_file: + for line in vlan_file: + if "Device:" in line: + dummy, dev = line.split() + break return dev

Royce, do you think it is related to issue https://github.com/kimchi-project/kimchi/issues/388 ? On 20/01/2015 06:45, lvroyce@linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce@linux.vnet.ibm.com>
File handler leak can be tested with following scripts against real model kimchi server, run "lsof -p $(kimchidpid)" and you can see many file opened without close.
import base64 import json import os import unittest import time
from functools import partial
from utils import request
host = None ssl_port = None
def setUpModule(): global host, ssl_port
host = '127.0.0.1' ssl_port = 8001
class RestTests(unittest.TestCase): def setUp(self): self.request = partial(request, host, ssl_port)
def test_leak(self): def fake_auth_header(): headers = {'Accept': 'application/json'} user, pw = ('my_username', 'my_passwd') hdr = "Basic " + base64.b64encode("%s:%s" % (user, pw)) headers['AUTHORIZATION'] = hdr return headers
def do_thousands(url): for i in range(1000): self.request(url, headers=fake_auth_header()) print "called %i times" % i
url = "https://%s:%s/toys" % \ (host, ssl_port) do_thousands(url)
Royce Lv (7): Fix md5 file handler leak Fix file handler leak for uptime file Close json schema file after loading close fh after iso scanning Fix leak in check_url_path Work around eventfd leak using multiprocessing Fix file handler leak in netinfo.py
src/kimchi/auth.py | 65 +++++++++++++++++++++++----------------- src/kimchi/isoinfo.py | 5 ++-- src/kimchi/model/debugreports.py | 5 ++-- src/kimchi/model/host.py | 5 ++-- src/kimchi/netinfo.py | 16 ++++++---- src/kimchi/root.py | 4 +-- src/kimchi/utils.py | 4 ++- 7 files changed, 61 insertions(+), 43 deletions(-)

On 22-01-2015 15:53, Aline Manera wrote:
Royce, do you think it is related to issue https://github.com/kimchi-project/kimchi/issues/388 ?
I'd say it's not. The issue is related to leaked processes, whereas this patchset is related to leaked file descriptors.

On 01/22/2015 02:00 PM, Crístian Viana wrote:
On 22-01-2015 15:53, Aline Manera wrote:
Royce, do you think it is related to issue https://github.com/kimchi-project/kimchi/issues/388 ?
I'd say it's not. The issue is related to leaked processes, whereas this patchset is related to leaked file descriptors. Agree, I haven't noticed any process leak during my test. but thousands of opening file handler.
participants (4)
-
Aline Manera
-
Crístian Viana
-
lvroyce@linux.vnet.ibm.com
-
Royce Lv