www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 21548] New: Thread.getThis().id is 0

https://issues.dlang.org/show_bug.cgi?id=21548

          Issue ID: 21548
           Summary: Thread.getThis().id is 0
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: critical
          Priority: P1
         Component: druntime
          Assignee: nobody puremagic.com
          Reporter: adam.furtenbach gmail.com

Created attachment 1813
  --> https://issues.dlang.org/attachment.cgi?id=1813&action=edit
Several program invocations

Assert in the following program sometimes hits.

Throws core.thread.osthread.ThreadException src/core/thread/osthread.d(867):
Unable to join thread if assert() is removed.


Tested on:

1)
DMD64 D Compiler v2.090.1

2)
DMD64 D Compiler v2.095.0

3)
LDC - the LLVM D compiler (1.23.0):
  based on DMD v2.093.1 and LLVM 10.0.1


Fail in ~1 of 300 program invocations. (see attached file)



import std.stdio;
import std.container : SList;
import core.thread;
import std.stdio;
import std.format;
import core.sync.mutex;
import core.sync.condition;
import core.memory;

public class Worker : Thread
{
    private void delegate() _func;
    private ThreadedExecutor _executor;

    public this(void delegate() func, ThreadedExecutor executor)
    {
        super(&Run);
        _func = func;
        _executor = executor;
    }

    private void Run()
    {
        try
        {
            _func();
        }
        catch (Throwable ex)
        {
            writeln(ex.msg);
        }

        _executor.Add(Thread.getThis());
    }
}

public class ThreadedExecutor
{
    private SList!Thread _expired;
    private Mutex _mutex;
    private Condition _condition;

    public this()
    {
        _mutex = new Mutex();
        _condition = new Condition(_mutex);
    }

    public void Start()
    {
        auto thread = new Thread(&Reap);

        thread.start();        
    }

    public void Execute(void delegate() func)
    {
        auto thread = new Worker(func, this);

        thread.start();
    }

    public void Add(Thread thread)
    {
        synchronized (_mutex)
        {
            _expired.insertFront(thread);
            _condition.notify();
        }
    }

    private void Reap()
    {
        while (true)
        {
            synchronized (_mutex)
            {
                while (_expired.empty())
                {
                    _condition.wait();
                }

                while (!_expired.empty())
                {
                    auto thread = _expired.front();

                    _expired.removeFront();
                    assert(thread.id != 0, "thread.id is zero...");
                    thread.join();
                }
            }
        }
    }
}

void main()
{
    GC.disable();
    writeln(Thread.getThis().id);
    auto executor = new ThreadedExecutor();
    void delegate() func = () {};

    executor.Start();
    executor.Execute(func);
}

--
Jan 14 2021