Page 1 of 1
[SOLVED] How do you keep track of destroyed threads?
Posted: Fri Oct 04, 2024 4:41 pm
by Oxmose
Hello everyone,
How to you keep track of destroyed (joined) threads?
For instance, if a thread was joined, its resources and its handle are freed.
What happens if another thread that has a handle to a destroyed threads perform an action (unlocking, blocking, signaling, etc.) on the destroyed thread?
My question would be, how can you check that the thread actually exists? I don't like having a flag in the thread structure because the released memory when destroying the thread can be re-used and the memory address where the destroyed thread flag was may be set to a value associated to an active thread.
Thanks!
Re: How do you keep track of destroyed threads?
Posted: Sat Oct 05, 2024 4:32 am
by iansjack
Obviously you shouldn't destroy a thread whilst there are open handles to it. The thread needs to keep a list of opened handles and signal the processes holding those handles when it is terminated. It should then wait until all open handles have been closed before the thread object is destroyed. That way the thread always exists when there are open handles to it; it's just that its state is TERMINATED.
It's the responsibility of the process that opened the handle to close it; otherwise you end up with a memory leak.
Re: How do you keep track of destroyed threads?
Posted: Sun Oct 06, 2024 8:01 am
by nullplan
In user-space: As per POSIX, a thread handle is valid from thread creation until clean-up. Detached threads clean themselves up on death, whereas joinable threads can be joined exactly once. As soon as that has happened, the thread handle is no longer valid, and any reference to it invokes undefined behavior.
Because detached threads clean themselves up, holding a handle to a detached thread is dangerous, unless synchronization is employed to prevent the handle becoming invalid. But if something like that is done, it is typically better to just use a joinable thread.
In kernel-space I am going to use a similar concept. The reason is simply this: thread handles can be re-used. As long as a thread handle has finite size, there are only finitely many threads it can identify, so unless thread handles can be re-used, the application (or kernel) would have to be restarted periodically to get rid of terminated thread handles.
Oxmose wrote: ↑Fri Oct 04, 2024 4:41 pm
My question would be, how can you check that the thread actually exists?
That is exactly the wrong question to ask. That is like asking how to check if a pointer is valid. You can't, and you can't check if a thread handle is valid. Rather, the calling application has to ensure the handle is valid, just as it has to ensure any pointer it passes is valid.
iansjack wrote: ↑Sat Oct 05, 2024 4:32 am
Obviously you shouldn't destroy a thread whilst there are open handles to it. The thread needs to keep a list of opened handles and signal the processes holding those handles when it is terminated. It should then wait until all open handles have been closed before the thread object is destroyed. That way the thread always exists when there are open handles to it; it's just that its state is TERMINATED.
This is basically a reference counted version of a joinable thread. However, since threads share memory, handles can be shared in a way your system doesn't notice. I think attempting to control sharing of data is a fool's errand, but you are welcome to try.
Re: How do you keep track of destroyed threads?
Posted: Sun Oct 06, 2024 8:38 am
by iansjack
In Widows a handle to a thread remains valid until it is closed, even if the thread it refers to has terminated. The Windows documentation states that
The handle is valid until closed, even after the thread it represents has been terminated.
...
Process and thread handles are signaled when the process or thread terminates. This allows a process, for example, to create a child process and then block its own execution until the new process has terminated.
Re: How do you keep track of destroyed threads?
Posted: Sun Oct 06, 2024 9:59 am
by Oxmose
Thank you both for the answers!
I was following the approach that nullplan explained and though there could be another solution. But I understand that ultimately there is none.
I was mainly asking that because my scheduler uses those handle to manage threads, meaning that an invalid action from the user could impact the functions of the whole system. I guess I will have to de-couple the handle used by the kernel itself and the handles that the user has. This way, worst case I just terminate the running process but the kernel stays in good shape.