Or at the github issue points out, if the thread will exit, LockOSThread my 
work.

On Tuesday, March 4, 2025 at 2:23:28 PM UTC-6 robert engels wrote:

> One way you can address this is to put a semaphore on the Go side around 
> the C call, so you ensure only so many C calls are made simultaneously.
>
>
> On Mar 4, 2025, at 1:26 PM, David Bell <davidbe...@gmail.com> wrote:
>
> *Hi everyone,*
>
> I'm relatively new to Go and even newer to *CGO*, so I’d really 
> appreciate any guidance on an issue I’ve been facing.
>
> *Problem Overview*
>
> I noticed that when using CGO, my application's *memory usage keeps 
> increasing*, and threads do not seem to be properly cleaned up. 
> The Go runtime (pprof) does not indicate any leaks, but when I monitor the 
> process using *Activity Monitor*, I see a growing number of threads and 
> increasing memory consumption.
> *Observations* 
>    
>    - Memory usage *keeps increasing* over time when using CGO, even after 
>    forcing garbage collection. 
>    - Threads spawned for CGO calls appear to *not be released*, causing a 
>    large number of lingering threads. 
>    - The issue is *not present* when using pure Go time.Sleep() instead 
>    of the CGO function. 
>
>
>
> *Reproducible Example*
>
> I created a minimal program that reproduces the issue. The following 
> *CGO-based* code keeps allocating memory and does not free threads 
> properly:
> package main
>
> import (
> "fmt"
> "runtime"
> "runtime/debug"
> "sync"
> "time"
> )
>
> /*
> #include <unistd.h>
> void cgoSleep() {
>   sleep(1);
> }
> */
> import "C"
>
> func main() {
> start := time.Now()
>
> var wg sync.WaitGroup
> for i := 0; i < 5000; i++ {
> wg.Add(1)
> go func() {
> defer wg.Done()
> C.cgoSleep()
> }()
> }
> wg.Wait()
>
> end := time.Now()
>
> // Force GC and free OS memory
> runtime.GC()
> debug.FreeOSMemory()
> time.Sleep(10 * time.Second)
>
> var m runtime.MemStats
> runtime.ReadMemStats(&m)
>
> fmt.Printf("Alloc = %v MiB", m.Alloc/1024/1024)
> fmt.Printf("\tTotalAlloc = %v MiB", m.TotalAlloc/1024/1024)
> fmt.Printf("\tSys = %v MiB", m.Sys/1024/1024)
> fmt.Printf("\tNumGC = %v\n", m.NumGC)
> fmt.Printf("Total time: %v\n", end.Sub(start))
>
> select {}
> }
>
> *Expected Behavior* 
>    
>    - The memory usage should *not* continue rising indefinitely. 
>    - Threads should be properly cleaned up when they finish executing. 
>    - The behavior should be similar to the following *pure Go* 
>    equivalent, which does *not* exhibit the issue: 
>
>
>
> *Actual Results* *With CGO (cgoSleep()):* 
>    
>    - *Memory Usage:* *296 MB* 
>    - *Threads:* *5,003* 
>    - *System Memory (Sys from runtime.MemStats)*: 
>
>
> *205 MB * 
>
> *With Pure Go (time.Sleep()):* 
>    
>    - *Memory Usage:* *14 MB* 
>    - *Threads:* *14* 
>    - *System Memory (Sys from runtime.MemStats)*: *24 MB* 
>
> *Additional Attempt*
>
> I tried forcing thread cleanup using runtime.LockOSThread() and 
> runtime.Goexit(), but *while the number of threads decreases, memory is 
> still never fully released*:
> go func() { runtime.LockOSThread() defer wg.Done() C.cgoSleep() 
> runtime.Goexit() }() *Questions* 
>    
>    1. *Why is memory increasing indefinitely with CGO?* 
>    2. *Why are threads not getting properly cleaned up after CGO calls?* 
>    3. *Is there a way to force the Go runtime to reclaim memory allocated 
>    for CGO threads?* 
>    4. *Is there a better approach to handling CGO calls that spawn 
>    short-lived threads?* 
>    5. *Would using runtime.UnlockOSThread() help in this case, or is this 
>    purely a CGO threading issue?* 
>    6. *Is there a way to track down where the memory is being held? Since 
>    pprof does not show high memory usage, what other tools can I use?* 
>
> *Go Version* 
> go1.23.5 darwin/arm64
>
> -- 
> You received this message because you are subscribed to the Google Groups 
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to golang-nuts...@googlegroups.com.
> To view this discussion visit 
> https://groups.google.com/d/msgid/golang-nuts/5e8c1622-e6f0-47a8-a869-e78797800fb5n%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/golang-nuts/5e8c1622-e6f0-47a8-a869-e78797800fb5n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/golang-nuts/c0bc498a-78b4-4e28-a470-be70c6a95b58n%40googlegroups.com.

Reply via email to