Skip to content

PortableThreadPool can't initialize in DPDK app #116850

Closed
@landerverhacklansweeper

Description

Description

The PortableThreadPool doesn't work when also using Data Plane Development Kit (DPDK).

Any attempt to run C# code that requires the ThreadPool crashes with the following trace:

Unhandled Exception: System.OutOfMemoryException: Insufficient memory to continue the execution of the program.
   at System.Threading.Thread.StartCore() + 0xa5
   at System.Threading.PortableThreadPool.GateThread.CreateGateThread() + 0x92

This is part of a C# library built as a Navtive .so lib for Linux.

Reproduction Steps

Create a simple C# library that uses a Task.

public static class ThreadPoolIssue
{
    [UnmanagedCallersOnly(EntryPoint = "test_task")]
    public static void TestTask()
    {
        Console.WriteLine("Starting task");
        Task.Delay(1000).ContinueWith(t =>
        {
            Console.WriteLine("Task completed after 1 second delay");
        });
    }
}

Publish the library using AOT for Linux
lin-x64.pubxml

<?xml version="1.0" encoding="utf-8"?>
<Project>
	<PropertyGroup>
		<Configuration>Release</Configuration>
		<Platform>Any CPU</Platform>
		<PublishDir>..\publish\</PublishDir>
		<PublishProtocol>FileSystem</PublishProtocol>
		<_TargetId>Folder</_TargetId>
		<TargetFramework>net9.0</TargetFramework>
		<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
		<SelfContained>true</SelfContained>
		<PublishAot>true</PublishAot>
	</PropertyGroup>
</Project>
dotnet publish -p:PublishProfile=lin-x64.pubxml

Create sample C application
testapp.h

#ifndef TESTAPP_H
#define TESTAPP_H

#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

void test_task();

#ifdef __cplusplus
}
#endif

#endif // TESTAPP_H

testapp.c

#include "testapp.h"
#include <unistd.h> // Include this header for sleep

int main(int argc, char* argv[])
{
	test_task();
	sleep(10); // Sleep for 10 seconds to allow threads to complete

	return 0;
}

Compile the C application (adjust paths if needed)

gcc -g -o ./publish/testapp ./ThreadPoolIssueLib/testapp.c -L./publish -lThreadPoolIssue -ldl -lpthread -lm -Wl,-rpath='$ORIGIN'

Verify that the application run outside of DPDK (this should work):

cd ./publish
./testapp

set up DPDK:
https://learn.microsoft.com/en-us/azure/virtual-network/setup-dpdk?tabs=ubuntu

Run code inside DPDK application --> see crash
(https://core.dpdk.org/doc/quick-start/)
Even though the creation of the GateThread fails, I can see the output of the Task after one second.

Expected behavior

The thread pool should initialize correctly. The application should not crash.

Actual behavior

Crashes with the following StackTrace:

Unhandled Exception: System.OutOfMemoryException: Insufficient memory to continue the execution of the program.
   at System.Threading.Thread.StartCore() + 0xa5
   at System.Threading.PortableThreadPool.GateThread.CreateGateThread() + 0x92

The task does seem to run though The stdout does show "Task completed after 1 second delay" after one second.

Regression?

No response

Known Workarounds

No response

Configuration

I tested multiple combinations. All with the same behavior.

Ubuntu 18.04 and 24.04 (x64)
.NET SDK 8.0.411, 9.0.301
.NET runtimes Microsoft.NETCore.App 8.0.17, Microsoft.NETCore.App 9.0.6
DPDK 21.11.0

Other information

    [UnmanagedCallersOnly(EntryPoint = "test_thread")]
    public static void TestTread()
    {
        Console.WriteLine("Starting thread");
        Thread thread = new(() =>
        {
            Console.WriteLine("Thread started");
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine($"Thread running iteration {i + 1}");
                Thread.Sleep(1000);
            }
            Console.WriteLine("Thread completed");
        });
        thread.Start();
    }
  • DPDK uses core pinning
  • DPDK uses huge pages
  • Any code that doesn't use the thread pool seems to run fine

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions