Skip to content

Fix for memory leaks and resource management bugs - #109

Closed
Lokesh Muthuraj (lokeshmuthuraj) wants to merge 6 commits into
microsoft:masterfrom
lokeshmuthuraj:fix/memory-leaks-resource-management-bug
Closed

Fix for memory leaks and resource management bugs#109
Lokesh Muthuraj (lokeshmuthuraj) wants to merge 6 commits into
microsoft:masterfrom
lokeshmuthuraj:fix/memory-leaks-resource-management-bug

Conversation

@lokeshmuthuraj

@lokeshmuthuraj Lokesh Muthuraj (lokeshmuthuraj) commented May 5, 2026

Copy link
Copy Markdown
Contributor

Fix: Memory Leaks and Resource Management (17 Issues)

Overview

This PR was initiated to fix issue #108.

However, this PR now fixes 17 memory and resource management bugs discovered through systematic code review, AddressSanitizer (ASAN/LSan), and Valgrind analysis of the ntttcp-for-linux codebase. The bugs fall into three categories:

  • Heap memory leaks — allocated memory never freed (malloc, strdup, ASPRINTF)
  • File descriptor leaks — sockets and file handles not closed in error paths or at function exit
  • Logic error — wrong constant passed to socket() in UDP sender

All issues were found on the unfixed codebase. Evidence sections below reproduce each leak using the commands shown. Later, after fixing the bugs, AddressSanitizer and Valgrind tests were executed again on the fixed codebase to check if the leaks were fixed.

Test Setup

ASAN build:

make CFLAGS="-g -O1 -fsanitize=address,leak -fno-omit-frame-pointer" LDFLAGS="-fsanitize=address,leak"
export ASAN_OPTIONS="detect_leaks=1:leak_check_at_exit=1:exitcode=23"
# Exit code 23 = leaks detected; 0 = clean

Valgrind build:

make CFLAGS="-g -O0 -fno-omit-frame-pointer"
VG="valgrind"
VG_OPTS="--track-fds=yes --leak-check=full --show-leak-kinds=all --num-callers=12 --error-exitcode=1"

Files Changed

File Issues Fixed
src/parameter.c Bug1 — strdup leak in process_mappings()
src/main.c Bug2 — sync socket not closed in sender error paths
src/udpstream.c Bug3, Bug4, Bug5, Bug6, Bug15, Bug16 — log leaks, buffer/socket leak, socket type bug, bind loop FD leak
src/endpointsync.c Bug7, Bug8, Bug13 — redundant alloc, double malloc, missing freeaddrinfo, FD leaks
src/tcpstream.c Bug9, Bug10, Bug11, Bug12 — FD leaks, log realloc leak in bind and accept error paths
src/ntttcp.c Bug14 — threads result array never freed
src/oscounter.c Bug17 — /proc/interrupts FD not closed on early return

Issues Fixed


Bug1 · parameter.cstrdup result leaked in process_mappings()

How found: ASAN, static analysis
Location: parameter.c:204

Root cause: process_mappings() calls strdup(test->mapping) and stores the result in element. strsep() then advances the element pointer. When an invalid CPU ID is detected, the function returns ERROR_ARGS without freeing the original allocation.

// BEFORE (buggy)
element = strdup(test->mapping);   // line 204 — original pointer saved
...
strsep(&element, ",");             // element pointer advances
...
if (cpu_n >= MAX_CPU_COUNT)
    return ERROR_ARGS;             // BUG: original strdup allocation never freed

Fix: Save the original pointer on entry and free() it in every return path.

Evidence (ASAN):

./ntttcp -r -m "4,9999,127.0.0.1"
# Exit 23
Direct leak of 17 byte(s) in 1 object(s) allocated from:
    #0 in strdup          asan_interceptors.cpp:578
    #1 in process_mappings parameter.c:204
    #2 in parse_arguments  parameter.c:461
    #3 in main             main.c:337

SUMMARY: AddressSanitizer: 33 byte(s) leaked in 2 allocation(s).

Bug2 · main.c — sync socket not closed in run_ntttcp_sender() error paths

How found: Static analysis, valgrind --track-fds=yes
Location: main.c:38–47

Root cause: synch_socket is opened at the start of run_ntttcp_sender() but is not closed before the return ERROR_GENERAL statements in the error paths at lines ~43 and ~47.

Fix: Added close(tep->synch_socket) before each return ERROR_GENERAL in the error paths.

Evidence: File descriptor leak confirmed with valgrind --track-fds=yes ./ntttcp -s 127.0.0.1. LSAN does not track FD leaks.


Bug3 · udpstream.cASPRINTF log leaked on early return in run_ntttcp_sender_udp4_stream()

How found: ASAN, static analysis
Location: udpstream.c:60, 68

Root cause: When get_interface_name_by_ip() or update_client_info() fails, the function allocates a log string with ASPRINTF(&log, ...) and then calls PRINT_ERR(log). The PRINT_ERR macro prints but does not free log.

// BEFORE (buggy)
ASPRINTF(&log, "failed to get interface ...");
PRINT_ERR(log);   // BUG: log is printed but never freed
return NULL;

Fix: Changed to PRINT_ERR_FREE(log), which prints and frees the string.

Evidence (ASAN):

./ntttcp -s 127.0.0.1 -u -a 192.0.2.1 -N -t 1 -P 1
# Exit 23
Direct leak of 208 byte(s) in 4 object(s) allocated from:
    #0 in malloc                         asan_malloc_linux.cpp:69
    #1 in asprintf                       stdio2.h:137
    #2 in run_ntttcp_sender_udp4_stream  udpstream.c:57
    #3 in run_ntttcp_sender_udp_stream   udpstream.c:16

SUMMARY: AddressSanitizer: 208 byte(s) leaked in 4 allocation(s).

(208 bytes = ~52-byte log string × 4 sender threads)


Bug4 · udpstream.cASPRINTF log leaked in socket error paths

How found: Static analysis
Location: udpstream.c:89, 99, 119

Root cause: Same ASPRINTF + PRINT_ERR(log) pattern as issue Bug3. Triggered when socket(), setsockopt(), or connect() fails.

Fix: Changed all three occurrences from PRINT_ERR(log) to PRINT_ERR_FREE(log).


Bug5 · udpstream.c — log string leaked via ASPRINTF overwrite in receiver bind path

How found: Static analysis
Location: udpstream.c:252

Root cause: The pattern ASPRINTF(&log, "%s. errcode=%d", log, errno) overwrites the log pointer with a new allocation without freeing the old one first. The original allocation at log is lost.

// BEFORE (buggy)
ASPRINTF(&log, "bind error ...");
if (ret == -1)
    ASPRINTF(&log, "%s. errcode=%d", log, errno);  // BUG: old log ptr overwritten

Fix:

char *old_log = log;
ASPRINTF(&log, "%s. errcode=%d", old_log, errno);
free(old_log);

Bug6 · udpstream.c — receive buffer and socket not freed on function exit

How found: ASAN
Location: udpstream.c:268 (buffer allocation), end of run_ntttcp_receiver_udp4_stream()

Root cause: buffer = malloc(udp_recv_size) (65,536 bytes) is allocated for the receive loop but never freed before the function returns. sockfd is also not closed.

Fix: Added free(buffer) and close(sockfd) before the function returns.

Evidence (ASAN):

./ntttcp -r 127.0.0.1 -t 3 -P 1 -u -N
# Exit 23
Direct leak of 65536 byte(s) in 1 object(s) allocated from:
    #0 in malloc                           asan_malloc_linux.cpp:69
    #1 in run_ntttcp_receiver_udp4_stream  udpstream.c:268
    #2 in run_ntttcp_receiver_udp_stream   udpstream.c:183

SUMMARY: AddressSanitizer: 65544 byte(s) leaked in 2 allocation(s).

(65,544 = 65,536-byte buffer + 8-byte threads array from issue Bug14)


Bug7 · endpointsync.c — redundant ip_address_max_size assignment removed

How found: Static analysis
Location: endpointsync.c:45

Root cause: ip_address_max_size was assigned twice — the second assignment was redundant and had no effect. Not a leak, but a code clarity fix.

Fix: Removed the duplicate assignment.


Bug8 · endpointsync.c — double malloc of ip_address_str + missing freeaddrinfo()

How found: Valgrind, static analysis
Location: endpointsync.c:327, 336 in create_receiver_sync_socket()

Root cause:

  1. ip_address_str is allocated with malloc(INET_ADDRSTRLEN) at line 327, then immediately allocated again at line 336. The first allocation is overwritten and leaked (16 bytes).
  2. getaddrinfo() result (serv_info) allocated at line 320 is never freed with freeaddrinfo() (64 bytes).

Fix: Removed the duplicate ip_address_str allocation; added freeaddrinfo(serv_info) after use.

Evidence (Valgrind):

$VG $VG_OPTS ./ntttcp -r 127.0.0.1 -t 5 -P 1 -n 1
==34545== 16 bytes in 1 blocks are definitely lost
==34545==    by create_receiver_sync_socket (endpointsync.c:327)

==34545== 64 bytes in 1 blocks are definitely lost
==34545==    by getaddrinfo (getaddrinfo.c:2391)
==34545==    by create_receiver_sync_socket (endpointsync.c:320)

LEAK SUMMARY: definitely lost: 96 bytes in 3 blocks

Bug9 · tcpstream.csockfd not closed in bind-retry loop in ntttcp_server_listen()

How found: Static analysis, valgrind --track-fds=yes
Location: tcpstream.c:375

Root cause: ntttcp_server_listen() iterates through getaddrinfo() results trying to bind. A new sockfd is opened on each iteration via socket(). When bind() fails the loop calls continue without closing sockfd first.

Fix: Added close(sockfd) before continue in the bind-failure path.


Bug10 · tcpstream.c — log string leaked via ASPRINTF overwrite in ntttcp_server_listen()

How found: Valgrind, static analysis
Location: tcpstream.c:367

Root cause: Same overwrite pattern as issue Bug5. When bind() fails, the function builds an error string by overwriting log with ASPRINTF(&log, "%s. errcode=%d", log, errno), losing the original pointer.

Fix: Same pattern — save the old pointer before overwriting and free it afterwards.

Evidence (Valgrind):

# Run when port 5001 is already occupied
$VG $VG_OPTS ./ntttcp -r 127.0.0.1 -t 2 -P 1 -n 1 -N
==37431== 80 bytes in 1 blocks are definitely lost
==37431==    by asprintf   (asprintf.c:31)
==37431==    by ntttcp_server_listen (tcpstream.c:367)

LEAK SUMMARY: definitely lost: 80 bytes in 1 blocks

Bug11 · tcpstream.cnewfd not closed in ntttcp_server_epoll() error paths

How found: Static analysis, valgrind --track-fds=yes
Location: tcpstream.c:500–511, 532

Root cause: accept() returns newfd. If set_socket_non_blocking(), set_socket_tcp_nodelay(), or epoll_ctl() subsequently fails, the code logs an error and continues without calling close(newfd). Each such failure leaks a socket descriptor.

Fix: Added close(newfd) before each continue in the failure paths.

Evidence (ASAN — epoll receiver, no-sync):

export ASAN_OPTIONS="detect_leaks=1:leak_check_at_exit=1:exitcode=23"
./ntttcp -r 127.0.0.1 -t 5 -P 1 -n 1 -e -N -p 5700 >/tmp/epoll_recv.txt 2>&1 &
RPID=$!; sleep 2
./ntttcp -s 127.0.0.1 -t 5 -P 1 -n 1 -N -p 5700 >/tmp/epoll_send.txt 2>&1
wait $RPID

Receiver ASAN output shows only the threads array leak (Bug14) — no new heap leaks. The newfd FD leak is not detectable by LSAN; use valgrind --track-fds=yes to confirm.


Bug12 · tcpstream.cnewfd not closed in ntttcp_server_select() error paths

How found: Valgrind, static analysis
Location: tcpstream.c:647–656

Root cause: Same pattern as issue Bug11, in the select()-based path. newfd from accept() is not closed when set_socket_non_blocking() or set_socket_tcp_nodelay() fails.

Fix: Added close(newfd) before each continue in the failure paths.

Evidence (Valgrind):

$VG $VG_OPTS ./ntttcp -r 127.0.0.1 -t 5 -P 1 -n 1
==34545== FILE DESCRIPTORS: 6 open (3 std) at exit.
==34545== Open AF_INET socket 7: 127.0.0.1:5001 <-> 127.0.0.1:47659
==34545==    by accept         (accept.c:26)
==34545==    by ntttcp_server_select (tcpstream.c:629)

Bug13 · endpointsync.cnewfd not closed in sync socket accept handling

How found: Static analysis
Location: endpointsync.c:399–407 in create_receiver_sync_socket()

Root cause: newfd from accept() in the sync connection handler is not closed when set_socket_non_blocking() or epoll_ctl() fails, leaking the descriptor.

Fix: Added close(newfd) before each continue in the failure paths.


Bug14 · ntttcp.ce->results->threads array pointer never freed

How found: ASAN, Valgrind
Location: ntttcp.c:160 (alloc), ntttcp.c:229 (teardown)

Root cause: new_ntttcp_test_endpoint() allocates an array of ntttcp_test_endpoint_thread_result* pointers at line 160. free_ntttcp_test_endpoint_and_test() correctly frees each individual element in the array, but never frees the array itself before freeing e->results.

// BEFORE (buggy): only element contents freed, not the array
for (i = 0; i < total_threads; i++)
    free(e->results->threads[i]);
// BUG: free(e->results->threads) never called
free(e->results);

Fix: Added free(e->results->threads) after the loop, before free(e->results).

Evidence (ASAN) — present in every test run:

./ntttcp -s 127.0.0.1 -t 3 -P 2 -n 1   # TCP sender, 2 ports × 1 thread = 16 bytes
Direct leak of 16 byte(s) in 1 object(s) allocated from:
    #0 in malloc                   asan_malloc_linux.cpp:69
    #1 in new_ntttcp_test_endpoint ntttcp.c:160
    #2 in main                     main.c:381

SUMMARY: AddressSanitizer: 16 byte(s) leaked in 1 allocation(s).

Evidence (Valgrind) — all four roles:

Role Leak Command
TCP sender (1P×1T) 8 bytes ./ntttcp -s 127.0.0.1 -t 5 -P 1 -n 1
TCP receiver (1P) 16 bytes ./ntttcp -r 127.0.0.1 -t 5 -P 1 -n 1
UDP sender (1P) 32 bytes ./ntttcp -s 127.0.0.1 -t 5 -P 1 -u -N
UDP receiver (1P, -N) 8 bytes ./ntttcp -r 127.0.0.1 -t 5 -P 1 -u -N

Leak size = sizeof(void *) × total_threads (8 bytes per pointer on 64-bit).


Bug15 · udpstream.c — wrong socket() type parameter in UDP sender

How found: Static analysis
Location: udpstream.c:72 in run_ntttcp_sender_udp4_stream()

Root cause: The socket() system call receives sc->domain (the address family, e.g. AF_INET = 2) as both the first and second argument. The second argument should be the socket type (SOCK_DGRAM).

// BEFORE (buggy)
sockfd = socket(sc->domain, sc->domain, 0);  // sc->domain used as socket type — wrong

On Linux AF_INET == SOCK_DGRAM == 2, so IPv4 UDP works by coincidence. With IPv6 (AF_INET6 = 10), this becomes socket(AF_INET6, 10, 0) = socket(AF_INET6, SOCK_RAW, 0), silently creating a raw socket instead of a datagram socket.

Fix:

sockfd = socket(sc->domain, UDP, 0);   // UDP is defined as SOCK_DGRAM

Bug16 · udpstream.csockfd not closed in bind-retry loop in UDP receiver

How found: Static analysis, valgrind --track-fds=yes
Location: udpstream.c:247 in run_ntttcp_receiver_udp4_stream()

Root cause: The function iterates through getaddrinfo() results trying to bind. A new socket is created on each iteration. When bind() fails the loop calls continue without closing sockfd first.

// BEFORE (buggy)
if (bind(sockfd, ...) < 0) {
    ...
    continue;   // BUG: sockfd not closed before retrying
}

Fix: Added close(sockfd) before continue.

Evidence: Confirmed by valgrind --track-fds=yes ./ntttcp -r -u. Valgrind reports the successfully-bound socket as open at exit (since close(sockfd) is also missing at function return — fixed by issue Bug6).


Bug17 · oscounter.c/proc/interrupts file descriptor not closed on early return

How found: Valgrind (new bug discovered during testing)
Location: oscounter.c:85 in get_interrupts_from_proc_by_dev()

Root cause: The function opens /proc/interrupts with fopen() at line 85, then checks whether dev_name is empty. The default value of show_dev_interrupts is "" (see ntttcp.c:53), so this early-return path is taken on every normal test execution. The fclose() at the end of the function is never reached.

FILE *file = fopen(PROC_FILE_INTERRUPTS, "r");   // FD opened
if (!strcmp(dev_name, ""))
    return 0;   // BUG: fclose(file) never called; FD + 472-byte FILE buffer leaked

run_ntttcp_throughput_management() calls this function twice (lines 161 and 194), so 2 FDs and 944 bytes are leaked on every test run by both sender and receiver.

Fix:

if (!strcmp(dev_name, "")) {
    fclose(file);   // close before early return
    return 0;
}

Evidence (Valgrind — TCP sender, default flags):

$VG $VG_OPTS ./ntttcp -s 127.0.0.1 -t 5 -P 1 -n 1
FILE DESCRIPTORS: 5 open (3 std) at exit.

Open file descriptor 5: /proc/interrupts
   by fopen@@GLIBC_2.2.5 (iofopen.c:86)
   by get_interrupts_from_proc_by_dev (oscounter.c:85)
   by run_ntttcp_throughput_management (throughputmanagement.c:161)

Open file descriptor 4: /proc/interrupts
   by fopen@@GLIBC_2.2.5 (iofopen.c:86)
   by get_interrupts_from_proc_by_dev (oscounter.c:85)
   by run_ntttcp_throughput_management (throughputmanagement.c:194)

472 bytes in 1 blocks are still reachable
   by fopen@@GLIBC_2.2.5 (iofopen.c:86)
   by get_interrupts_from_proc_by_dev (oscounter.c:85)
   by run_ntttcp_throughput_management (throughputmanagement.c:161)

472 bytes in 1 blocks are still reachable
   by fopen@@GLIBC_2.2.5 (iofopen.c:86)
   by get_interrupts_from_proc_by_dev (oscounter.c:85)
   by run_ntttcp_throughput_management (throughputmanagement.c:194)

LEAK SUMMARY: still reachable: 944 bytes in 2 blocks
ERROR SUMMARY: 3 errors from 3 contexts

Confirmed in all four roles: TCP sender, TCP receiver, UDP sender, UDP receiver.
When --show-dev-interrupts is given a non-empty device name, the FDs are closed correctly and no leak appears.


Detection Methods Summary

Method Bugs Found Notes
ASAN / LSan Bug1, Bug3, Bug6, Bug10, Bug14 (heap) Cannot detect FD leaks
Valgrind --leak-check=full Bug8, Bug10, Bug14, Bug17 (heap+FILE*)
Valgrind --track-fds=yes Bug2, Bug9, Bug11, Bug12, Bug13, Bug16 (FD) Detects FD leaks
Static analysis All 17 Used to confirm and find remaining issues

How to Verify After This PR

make CFLAGS="-g -O1 -fsanitize=address,leak -fno-omit-frame-pointer" LDFLAGS="-fsanitize=address,leak"
export ASAN_OPTIONS="detect_leaks=1:leak_check_at_exit=1:exitcode=23"

# TCP test (receiver + sender, no-sync for clean exit)
./ntttcp -r 127.0.0.1 -t 5 -P 2 -n 1 -N >/tmp/recv.txt 2>&1 &
RPID=$!; sleep 1
./ntttcp -s 127.0.0.1 -t 5 -P 2 -n 1 -N; echo "SENDER=$?"
wait $RPID; echo "RECV=$?"
# Expected: both exit 0 (no leaks)

# UDP test
./ntttcp -r 127.0.0.1 -t 5 -P 1 -u -N; echo "UDP_RECV=$?"
# Expected: exit 0

Post-Fix Verification Results

All tests run on the fixed codebase. ASAN build + ASAN_OPTIONS="detect_leaks=1:leak_check_at_exit=1:exitcode=23".

ASAN Results

TCP sender (no-sync) — exit 0, no leaks:

$ ./ntttcp -s 127.0.0.1 -t 5 -P 1 -n 1 -N; echo "TCP_SENDER=$?"
TCP_SENDER=0

UDP sender + receiver (no-sync) — both exit 0:

$ ./ntttcp -s 127.0.0.1 -t 5 -P 1 -u -N; echo "UDP_SENDER=$?"
UDP_SENDER=0

$ ./ntttcp -r 127.0.0.1 -t 5 -P 1 -u -N; echo "UDP_RECV=$?"
UDP_RECV=0

1 process_mappings strdup — no longer leaks (was exit 23):

$ ./ntttcp -r -m "4,9999,127.0.0.1"; echo "EXIT=$?"
07:48:12 ERR : process_mappings: cpu specified is not in allowed scope
EXIT=1
# No ASAN ERROR output — previously: "SUMMARY: AddressSanitizer: 33 byte(s) leaked"

Bug3 UDP bogus interface log leak — no longer leaks (was exit 23):

$ ./ntttcp -s 127.0.0.1 -u -a 192.0.2.1 -N -t 2 -P 1 -n 1; echo "EXIT=$?"
07:51:09 ERR : failed to get interface name by address [192.0.2.1]
EXIT=1
# No ASAN ERROR output — previously: "SUMMARY: AddressSanitizer: 208 byte(s) leaked"

Valgrind Results

Build: make CFLAGS="-g -O0 -fno-omit-frame-pointer"
Flags: --track-fds=yes --leak-check=full --show-leak-kinds=all --error-exitcode=1

UDP sender — clean (previously: threads array + socket FD leaks):

==60442== FILE DESCRIPTORS: 3 open (3 std) at exit.
==60442== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

UDP receiver — clean (previously: 65,536-byte buffer + threads array leaked):

==61244== FILE DESCRIPTORS: 3 open (3 std) at exit.
==61244== All heap blocks were freed -- no leaks are possible
==61244== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

TCP sender — clean (previously: Bug17 /proc/interrupts FDs open, 944 bytes reachable):

==60338== FILE DESCRIPTORS: 3 open (3 std) at exit.
==60338== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Previously (unfixed TCP sender, Bug17):

==XXXXX== FILE DESCRIPTORS: 5 open (3 std) at exit.
==XXXXX== Open file descriptor 5: /proc/interrupts
==XXXXX== Open file descriptor 4: /proc/interrupts
==XXXXX== LEAK SUMMARY: still reachable: 944 bytes in 2 blocks
==XXXXX== ERROR SUMMARY: 3 errors from 3 contexts

Functional Tests Pass

image

@lokeshmuthuraj

Copy link
Copy Markdown
Contributor Author

Copilot review

@lokeshmuthuraj

Copy link
Copy Markdown
Contributor Author

Simon Xiao (@simonxiaoss) lubaihua33 Please review the PR. I don't have permission to add Copilot as reviewer as well.

@lubaihua33

Copy link
Copy Markdown
Collaborator

Simon Xiao (@simonxiaoss) lubaihua33 Please review the PR. I don't have permission to add Copilot as reviewer as well.

Hi Lokesh Muthuraj (@lokeshmuthuraj), thanks for your fix. I have requested copilot to review.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets issue #108 by addressing a set of memory leaks and resource-management bugs (heap allocations and file descriptors) across sender/receiver, TCP/UDP, sync, and OS counter paths.

Changes:

  • Fixes multiple asprintf/log-string leaks by switching to PRINT_*_FREE() and avoiding ASPRINTF overwrite leaks.
  • Closes leaked sockets / file handles in several error paths and on function exit (TCP/UDP streams, sender sync, /proc/interrupts reader).
  • Fixes a UDP sender socket creation bug by using the correct socket type (SOCK_DGRAM).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/udpstream.c Fixes UDP sender log leaks, corrects UDP socket type, and adds missing close/free in receiver paths.
src/tcpstream.c Fixes TCP listener error-path cleanup and closes accepted sockets on failure paths in epoll/select loops.
src/parameter.c Adjusts mapping parsing cleanup on error paths and adds an allocation failure check.
src/oscounter.c Ensures /proc/interrupts FILE* is closed on early return.
src/ntttcp.c Frees the thread-result pointer array (e->results->threads).
src/main.c Closes the sender sync socket on additional sender error/exit paths.
src/endpointsync.c Improves receiver sync socket cleanup and adds missing frees/closes in failure paths.
src/const.h Bumps tool version to 1.4.4.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/endpointsync.c
Comment thread src/parameter.c Outdated
Comment thread src/udpstream.c Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.

Comment thread src/udpstream.c
Comment thread src/parameter.c
Comment thread src/main.c
Comment thread src/ntttcp.c Outdated
Comment thread src/endpointsync.c
Comment thread src/tcpstream.c
Comment thread src/udpstream.c

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (1)

src/parameter.c:1

  • free(e->test->bind_address) assumes bind_address is always heap-allocated. In verify_args (parameter.c around line 274), if strdup("::") fails, test->bind_address is left as NULL (after the preceding free) — that case is fine. However, more importantly, please verify all writes to test->bind_address consistently use strdup (including any code paths not shown here, e.g., when reading from config). One assignment to a string literal anywhere (such as the pre-existing test->client_address = "0.0.0.0" pattern) would make this free crash. Consider adding a helper like set_bind_address(test, value) to centralize the free+strdup logic and avoid future regressions.
// ----------------------------------------------------------------------------------

Comment thread src/endpointsync.c
Comment thread src/endpointsync.c
Comment thread test/functional_test.py Outdated
Comment thread src/udpstream.c Outdated
Comment thread src/ntttcp.c Outdated
Comment thread src/parameter.c

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.

Comment thread src/endpointsync.c
Comment thread src/endpointsync.c
Comment thread src/udpstream.c
Comment thread src/parameter.c
Comment thread src/main.c
Comment thread src/parameter.c
Comment thread src/ntttcp.c
Comment thread test/functional_test.py
Comment on lines +386 to 388

if __name__ == "__main__":
pytest.main()
@lokeshmuthuraj

Copy link
Copy Markdown
Contributor Author

lubaihua33 / Simon Xiao (@simonxiaoss) Copilot keeps on raising more code review comments and this is leading to increase in line of code. I have broken down this single PR #109 into multiple small PRs which are focused.

Please check and review the following PRs:
#110
#111
#112
#113

I will close this PR and it will be continued as part of the PRs #110 , #111 , #112 , #113

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants