Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc][test] fix memory leak #122378

Merged
merged 1 commit into from
Jan 9, 2025
Merged

Conversation

nickdesaulniers
Copy link
Member

Looks like the smart pointer I removed was being used to free the underlying
object.

Fixes: #122369

Looks like the smart pointer I removed was being used to free the underlying
object.

Fixes: llvm#122369
@llvmbot
Copy link
Member

llvmbot commented Jan 9, 2025

@llvm/pr-subscribers-libc

Author: Nick Desaulniers (nickdesaulniers)

Changes

Looks like the smart pointer I removed was being used to free the underlying
object.

Fixes: #122369


Full diff: https://github.com/llvm/llvm-project/pull/122378.diff

2 Files Affected:

  • (modified) libc/test/UnitTest/ExecuteFunctionUnix.cpp (+15-4)
  • (modified) libc/test/UnitTest/FPExceptMatcher.cpp (+1)
diff --git a/libc/test/UnitTest/ExecuteFunctionUnix.cpp b/libc/test/UnitTest/ExecuteFunctionUnix.cpp
index df71738668592a..b004e8c0891171 100644
--- a/libc/test/UnitTest/ExecuteFunctionUnix.cpp
+++ b/libc/test/UnitTest/ExecuteFunctionUnix.cpp
@@ -36,18 +36,23 @@ int ProcessStatus::get_fatal_signal() {
 
 ProcessStatus invoke_in_subprocess(FunctionCaller *func, unsigned timeout_ms) {
   int pipe_fds[2];
-  if (::pipe(pipe_fds) == -1)
+  if (::pipe(pipe_fds) == -1) {
+    ::free(func);
     return ProcessStatus::error("pipe(2) failed");
+  }
 
   // Don't copy the buffers into the child process and print twice.
   ::fflush(stderr);
   ::fflush(stdout);
   pid_t pid = ::fork();
-  if (pid == -1)
+  if (pid == -1) {
+    ::free(func);
     return ProcessStatus::error("fork(2) failed");
+  }
 
   if (!pid) {
     (*func)();
+    ::free(func);
     ::exit(0);
   }
   ::close(pipe_fds[1]);
@@ -57,11 +62,14 @@ ProcessStatus invoke_in_subprocess(FunctionCaller *func, unsigned timeout_ms) {
   };
   // No events requested so this call will only return after the timeout or if
   // the pipes peer was closed, signaling the process exited.
-  if (::poll(&poll_fd, 1, timeout_ms) == -1)
+  if (::poll(&poll_fd, 1, timeout_ms) == -1) {
+    ::free(func);
     return ProcessStatus::error("poll(2) failed");
+  }
   // If the pipe wasn't closed by the child yet then timeout has expired.
   if (!(poll_fd.revents & POLLHUP)) {
     ::kill(pid, SIGKILL);
+    ::free(func);
     return ProcessStatus::timed_out_ps();
   }
 
@@ -69,9 +77,12 @@ ProcessStatus invoke_in_subprocess(FunctionCaller *func, unsigned timeout_ms) {
   // Wait on the pid of the subprocess here so it gets collected by the system
   // and doesn't turn into a zombie.
   pid_t status = ::waitpid(pid, &wstatus, 0);
-  if (status == -1)
+  if (status == -1) {
+    ::free(func);
     return ProcessStatus::error("waitpid(2) failed");
+  }
   assert(status == pid);
+  ::free(func);
   return {wstatus};
 }
 
diff --git a/libc/test/UnitTest/FPExceptMatcher.cpp b/libc/test/UnitTest/FPExceptMatcher.cpp
index 889f9f6f44a913..928c3df6ac48a6 100644
--- a/libc/test/UnitTest/FPExceptMatcher.cpp
+++ b/libc/test/UnitTest/FPExceptMatcher.cpp
@@ -44,6 +44,7 @@ FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) {
   fputil::get_env(&oldEnv);
   if (sigsetjmp(jumpBuffer, 1) == 0)
     func->call();
+  free(func);
   // We restore the previous floating point environment after
   // the call to the function which can potentially raise SIGFPE.
   fputil::set_env(&oldEnv);

Copy link
Contributor

@jhuber6 jhuber6 left a comment

Choose a reason for hiding this comment

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

Do we have some sort of RAII wrapper that could handle this? Seems a little cumbersome to track each branch.

@nickdesaulniers
Copy link
Member Author

nickdesaulniers commented Jan 9, 2025

No; it's probably not too bad to add a cpp::unique_ptr to a newly created libc/src/__support/CPP/memory.h, but I'll leave that cleanup for another time when the build's not red.

@nickdesaulniers nickdesaulniers merged commit 3caa68a into llvm:main Jan 9, 2025
11 of 12 checks passed
@nickdesaulniers
Copy link
Member Author

still fails: https://lab.llvm.org/buildbot/#/builders/171/builds/13529. Hmm...did I miss something?

@nickdesaulniers
Copy link
Member Author

nickdesaulniers commented Jan 9, 2025

==3162239==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new vs free) on 0x602000000030
    #0 0x561c514c7f72 in __interceptor_free (/home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/build/libc/test/src/stdlib/libc.test.src.stdlib._Exit_test.__unit__.__build__+0xa8f72) (BuildId: 0cd81dae603618c82e6aada51fbc7571192885c3)
    #1 0x561c5151d7d0 in __llvm_libc_20_0_0_git::testutils::invoke_in_subprocess(__llvm_libc_20_0_0_git::testutils::FunctionCaller*, unsigned int) /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/llvm-project/libc/test/UnitTest/ExecuteFunctionUnix.cpp:85:3
    #2 0x561c5151c451 in __llvm_libc_20_0_0_git::testing::Test::testProcessExits(__llvm_libc_20_0_0_git::testutils::FunctionCaller*, int, char const*, char const*, __llvm_libc_20_0_0_git::testing::internal::Location) /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/llvm-project/libc/test/UnitTest/LibcDeathTestExecutors.cpp:72:7
    #3 0x561c51505869 in LlvmLibcStdlib__Exit::Run() /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/llvm-project/libc/test/src/stdlib/_Exit_test.cpp:14:3
0x602000000030 is located 0 bytes inside of 16-byte region [0x602000000030,0x602000000040)
allocated by thread T0 here:
    #0 0x561c51502fed in operator new(unsigned long) (/home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/build/libc/test/src/stdlib/libc.test.src.stdlib._Exit_test.__unit__.__build__+0xe3fed) (BuildId: 0cd81dae603618c82e6aada51fbc7571192885c3)
    #1 0x561c51505cd5 in __llvm_libc_20_0_0_git::testutils::FunctionCaller* __llvm_libc_20_0_0_git::testing::Test::createCallable<LlvmLibcStdlib__Exit::Run()::$_0>(LlvmLibcStdlib__Exit::Run()::$_0) /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/llvm-project/libc/test/UnitTest/LibcTest.h:221:12
    #2 0x561c5150576f in LlvmLibcStdlib__Exit::Run() /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/llvm-project/libc/test/src/stdlib/_Exit_test.cpp:14:3
    #3 0x561c5151ec57 in __llvm_libc_20_0_0_git::testing::Test::runTests(__llvm_libc_20_0_0_git::testing::TestOptions const&) /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/llvm-project/libc/test/UnitTest/LibcTest.cpp:165:8
    #4 0x561c515594f8 in main /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/llvm-project/libc/test/UnitTest/LibcTestMain.cpp:59:10
    #5 0x7f92a8246249 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

oh, do I need delete rather than free?

nickdesaulniers added a commit to nickdesaulniers/llvm-project that referenced this pull request Jan 9, 2025
These were created with operator new (see `Test::createCallable`), so operator
delete should be used instead of free().

Fixes: llvm#122369
Fixes: llvm#122378
nickdesaulniers added a commit that referenced this pull request Jan 9, 2025
These were created with operator new (see `Test::createCallable`), so operator
delete should be used instead of free().

Fixes: #122369
Fixes: #122378
@nickdesaulniers nickdesaulniers deleted the fix_leak branch January 9, 2025 23:25
BaiXilin pushed a commit to BaiXilin/llvm-fix-vnni-instr-types that referenced this pull request Jan 12, 2025
Looks like the smart pointer I removed was being used to free the underlying
object.

Fixes: llvm#122369
BaiXilin pushed a commit to BaiXilin/llvm-fix-vnni-instr-types that referenced this pull request Jan 12, 2025
These were created with operator new (see `Test::createCallable`), so operator
delete should be used instead of free().

Fixes: llvm#122369
Fixes: llvm#122378
Mel-Chen pushed a commit to Mel-Chen/llvm-project that referenced this pull request Jan 13, 2025
Looks like the smart pointer I removed was being used to free the underlying
object.

Fixes: llvm#122369
Mel-Chen pushed a commit to Mel-Chen/llvm-project that referenced this pull request Jan 13, 2025
These were created with operator new (see `Test::createCallable`), so operator
delete should be used instead of free().

Fixes: llvm#122369
Fixes: llvm#122378
DKLoehr pushed a commit to DKLoehr/llvm-project that referenced this pull request Jan 17, 2025
Looks like the smart pointer I removed was being used to free the underlying
object.

Fixes: llvm#122369
DKLoehr pushed a commit to DKLoehr/llvm-project that referenced this pull request Jan 17, 2025
These were created with operator new (see `Test::createCallable`), so operator
delete should be used instead of free().

Fixes: llvm#122369
Fixes: llvm#122378
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants