Skip to content

Commit

Permalink
ci: add open fds valgrind check (aws#4851)
Browse files Browse the repository at this point in the history
  • Loading branch information
boquan-fang authored Nov 12, 2024
1 parent 493b771 commit 0807885
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ if (BUILD_TESTING)
--error-limit=no \
--num-callers=40 \
--undef-value-errors=no \
--track-fds=yes \
--log-fd=2 \
--suppressions=valgrind.suppressions")

Expand Down
65 changes: 65 additions & 0 deletions codebuild/bin/s2n_open_fds_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

# This script parses the LastDynamicAnalysis file generated by Valgrind running through CTest memcheck.
# It identifies any leaking file descriptors and triggers an error when detected.
# This enhances the capabilities of existing Valgrind checks.
# Output snippet for open file descriptors:
# ==6652== FILE DESCRIPTORS: 6 open (3 std) at exit.
# ==6652== Open AF_INET socket 6: 127.0.0.1:36915 <-> unbound
# ==6652== at 0x498B2EB: socket (syscall-template.S:120)
# ==6652== by 0x16CD16: s2n_new_inet_socket_pair (s2n_self_talk_ktls_test.c:69)
# ==6652== by 0x15DBB2: main (s2n_self_talk_ktls_test.c:168)
# ==6652==
import os
import sys

EXIT_SUCCESS = 0
# Exit with error code 1 if leaking fds are detected.
ERROR_EXIT_CODE = 1
# This test is designed to be informational only, so we only print fifteen lines of error messages when a leak is detected.
NUM_OF_LINES_TO_PRINT = 15


def find_log_file(path):
for f in os.listdir(path):
if "LastDynamicAnalysis" in f:
return os.path.join(path, f)

raise FileNotFoundError("LastDynamicAnalysis log file is not found!")


def detect_leak(file):
fd_leak_detected = False
lines = file.readlines()
for i in range(len(lines)):
if "FILE DESCRIPTORS:" in lines[i]:
# Example line: `==6096== FILE DESCRIPTORS: 4 open (3 std) at exit.`
line_elements = lines[i].split()
open_fd_count = line_elements[line_elements.index("DESCRIPTORS:") + 1]
std_fd_count = line_elements[line_elements.index("std)") - 1][1:]
# CTest memcheck writes to a LastDynamicAnslysis log file.
# We allow that fd to remain opened.
if int(open_fd_count) > int(std_fd_count) + 1:
for j in range(NUM_OF_LINES_TO_PRINT):
print(lines[i + j], end="")
print()
fd_leak_detected = True
return fd_leak_detected


def main():
# Print banner of the test
print("############################################################################")
print("################# Test for Leaking File Descriptors ########################")
print("############################################################################")

with open(find_log_file(sys.argv[1]), 'r') as file:
if detect_leak(file):
sys.exit(ERROR_EXIT_CODE)

return EXIT_SUCCESS


if __name__ == '__main__':
main()
4 changes: 3 additions & 1 deletion codebuild/spec/buildspec_valgrind.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ batch:
- identifier: gcc_openssl_1_1_1
env:
compute-type: BUILD_GENERAL1_LARGE
image: 024603541914.dkr.ecr.us-west-2.amazonaws.com/docker:ubuntu18codebuild
image: 024603541914.dkr.ecr.us-west-2.amazonaws.com/docker:ubuntu24
variables:
S2N_LIBCRYPTO: openssl-1.1.1
COMPILER: gcc
Expand Down Expand Up @@ -70,3 +70,5 @@ phases:
CTEST_OUTPUT_ON_FAILURE=1 \
cmake --build build/ --target test \
-- ARGS="--test-action memcheck"
- cd codebuild/bin
- python3 s2n_open_fds_test.py $CODEBUILD_SRC_DIR/build/Testing/Temporary

0 comments on commit 0807885

Please sign in to comment.