1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- #!/usr/bin/env python
- # coding: UTF-8
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- # This script checks the valgrind output for errors.
- # The track-fds does not cause an error if there are too many FDs open,
- # therefore we parse the output and fail if there are open FDs
- import sys
- import subprocess
- import os.path
- import re
- logfile = sys.argv[1]
- valgrind_command = ' '.join('"' + item + '"' for item in sys.argv[2:])
- # Execute a command and output its stdout text
- def execute(command):
- process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- # Poll process for new output until finished
- while True:
- nextline = process.stdout.readline().decode('utf-8')
- if nextline == '' and process.poll() is not None:
- break
- sys.stdout.write(nextline)
- sys.stdout.flush()
- return process.returncode
- ret_code = execute(valgrind_command)
- if not os.path.isfile(logfile):
- print("### PYTHON ERROR: Valgrind logfile does not exist: " + logfile)
- exit(1)
- log_content = ""
- with open(logfile, 'r') as content_file:
- log_content = content_file.read()
- if len(log_content) == 0:
- print("### PYTHON ERROR: Valgrind logfile is empty: " + logfile)
- exit(1)
- # Try to parse the output. Look for the following line:
- # ==17054== FILE DESCRIPTORS: 5 open at exit.
- descriptors_re = re.compile(r"^==(\d+)==\s+FILE DESCRIPTORS: (\d+) open at exit.$", re.MULTILINE)
- m = descriptors_re.match(log_content)
- if not m:
- print("### PYTHON ERROR: File descriptors header not found: " + logfile)
- print(log_content)
- exit(1)
- log_content = descriptors_re.sub('', log_content)
- valgrind_number = m.group(1)
- open_count = int(m.group(2))
- # Remove the open file descriptors which are inherited from parent. they look like this:
- #==21343== Open file descriptor 3: /home/user/open62541/build/bin/tests/discovery.log
- #==21343== <inherited from parent>
- #==21343==
- #==21343== Open file descriptor 2:
- #==21343== <inherited from parent>
- #==21343==
- #==21343== Open file descriptor 1:
- #==21343== <inherited from parent>
- #==21343==
- #==21343== Open file descriptor 0: /dev/pts/1
- #==21343== <inherited from parent>
- replace_re = re.compile(r"^=="+str(valgrind_number)+r"==\s+Open file descriptor \d+:\s*[^\s]*$\n^=="+str(valgrind_number)+r"==\s+<inherited from parent>$\n(^=="+str(valgrind_number)+r"==\s+$\n)*", re.MULTILINE)
- log_content = replace_re.sub('', log_content)
- # Valgrind detected a memleak if ret_code != 0
- if ret_code != 0:
- print(log_content)
- exit(ret_code)
- # No issues by valgrind
- if log_content.isspace():
- exit(0)
- # There is something fishy in the valgrind output, so error-exit
- print(log_content)
- exit(1)
|