Skip to content

PThread Allocation Memory Leak #1223

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

Open
barisyild opened this issue May 13, 2025 · 0 comments
Open

PThread Allocation Memory Leak #1223

barisyild opened this issue May 13, 2025 · 0 comments

Comments

@barisyild
Copy link
Contributor

barisyild commented May 13, 2025

Tested on Windows and Linux.

Reproduce Code:

package;
import haxe.atomic.AtomicInt;
import sys.thread.Thread;
import sys.thread.Mutex;
import sys.thread.FixedThreadPool;

#if windows
@:cppFileCode("
#include <windows.h>
#include <psapi.h>
#include <iostream>

using namespace std;
")
#elseif linux
@:cppFileCode("
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
")
#elseif macos
@:cppFileCode("
#include <mach/mach.h>
")
#end

class MemoryTest {
    private static var completedCount:AtomicInt = new AtomicInt(0);
    private static var maxThreadCount:Int = 10;
    private static var activeThreadCount:AtomicInt = new AtomicInt(0);
    private static var workCount:Int = 100000;
    private static var mutex:Mutex = new Mutex();
    #if use_thread_pool
    private static var threadPool:FixedThreadPool = new FixedThreadPool(maxThreadCount);
    #end

    public static function main() {
        trace("Hello World!");


        cpp.vm.Gc.compact();
        cpp.vm.Gc.run(true);
        var firstUsage = getMemoryUsage();
        trace('Memory usage: ${firstUsage} byte');

        //Sys.sleep(10);

        while (true) {
            if (completedCount.load() >= workCount) {
                break;
            }

            trace('Completed: ${completedCount.load()} / ${workCount}');

            // Use mutex to safely check and update thread count
            mutex.acquire();
            while (activeThreadCount.load() < maxThreadCount) {
                activeThreadCount.add(1);
                createNewThread();
            }
            mutex.release();
        }


        while (activeThreadCount.load() != 0)
        {
            Sys.sleep(0.01);
        }

        #if (use_thread_pool && !loop)
        threadPool.shutdown();
        #end

        cpp.vm.Gc.compact();
        cpp.vm.Gc.run(true);
        var finalUsage = getMemoryUsage();
        trace('Memory usage: ${finalUsage} byte');

        var diff = finalUsage - firstUsage;
        trace('Memory usage diff: ${diff} byte');

        // Loop memory test
        #if loop
        while (true) {
            completedCount = new AtomicInt(0);
            activeThreadCount = new AtomicInt(0);
            Sys.sleep(1);
            main();
        }
        #end
    }

    private static function createNewThread():Void {

        #if use_thread_pool threadPool.run #else Thread.create #end(() -> {
            // When you activate it, memory leak is solved (Linux)
            #if false
            cpp.vm.Gc.compact();
            #end

            try {
                haxe.io.Bytes.alloc(1024 * 50);
            } catch (e:Dynamic) {
                trace('Thread error: $e');
            }

            mutex.acquire();
            completedCount.add(1);
            activeThreadCount.add(-1);
            mutex.release();

            // When you activate it, "Segmentation fault (core dumped)" occurs, is this a bug? (Linux)
            #if false
            cpp.vm.Gc.compact();
            #end
        });
    }

    #if windows
    private static function getMemoryUsage():Float
    {
        var usage:Float = 0;
        untyped __cpp__('
        HANDLE hProcess = GetCurrentProcess();

        // Bellek kullanım bilgilerini saklayacak değişken
        PROCESS_MEMORY_COUNTERS pmc;

            // Bellek kullanım bilgilerini alıyoruz
        if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
        {
            {0} = pmc.WorkingSetSize;
        }
        else
        {
            {0} = 0;
        }
        CloseHandle(hProcess);
        ', usage);
        return usage;
    }
    #elseif linux
    private static function getMemoryUsage():Int
    {
        untyped __cpp__('FILE *fp;
    char line[256];
    long memory = 0;

    // Open the /proc/self/status file
    fp = fopen("/proc/self/status", "r");
    if (fp == NULL) {
        perror("fopen");
        return -1;
    }

    // Read each line and look for the VmRSS field
    while (fgets(line, sizeof(line), fp)) {
        if (strncmp(line, "VmRSS:", 6) == 0) {
            // VmRSS is in kilobytes, so we convert it to a long
            sscanf(line, "VmRSS: %ld kB", &memory);
            break;
        }
    }

    fclose(fp);
    return memory * 1024;');

        return -1;
    }
    #elseif macos
    private static function getMemoryUsage():Int
    {
        untyped __cpp__('
         task_vm_info_data_t vm_info;
    mach_msg_type_number_t count = TASK_VM_INFO_COUNT;

    kern_return_t kr = task_info(
        mach_task_self(),
        TASK_VM_INFO,
        (task_info_t)&vm_info,
        &count
    );

    if (kr != KERN_SUCCESS) {
        return 1;
    }

    return (unsigned long long)vm_info.phys_footprint;
        ');
        return -1;
    }
    #end
}

Definitions:

-D HXCPP_VERBOSE
-D HXCPP_STACK_LINE
-D HXCPP_STACK_TRACE
-D HXCPP_CHECK_POINTER
-D HXCPP_CPP11
-D HXCPP_GC_MOVING

Memory Usage Diff:

Linux: 37650432 byte
Windows: 1314816 byte
@barisyild barisyild changed the title Thread Allocation Memory Leak PThread Allocation Memory Leak May 13, 2025
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

No branches or pull requests

1 participant