Melzzzzz <
Melz...@zzzzz.com> writes:
>On 2020-12-13, Bonita Montero <
Bonita....@gmail.com> wrote:
>> I had a nice bug: I've got a base-class with a pure virtual function
>> which is overridden in a derived class. This function is virtually
>> called by a thread from a thread pool (through a static proxy-func-
>> tion). In the destructor of the base-class I wait for all threads
>> from the thread pool to have finished their work and that there are
>> no more items in their work-queue.
>> What I missed was, that as soon as the base-class destructor is called
>> the virtual fuction pointer is adjusted to the pointer of the base-class
>> (I'm wondering that is there any because a base-class with a pure vir-
>> tual function shouldn't have a virtual method table at all). So before
>> I could wait for the threads to finish all work the null pure virtual
>> function got called. ;-)
>> Interestingly this doesn't happen if I don't compile the code as debug
>> -code. So the compiler indirectly gives me a hint here for a possible
>> bug.
>
>Joinining in destructor was always no no if Java model is used.
>Not once I saw pworblems with this in RL.
bool in_context(void) const { return t_thread == pthread_self(); }
c_thread::~c_thread(void)
{
lock();
terminate();
unlock();
}
/**
* Terminate the thread. If called in-context, it will clear the
* running flag and exit. If called out of context, it will cancel
* the thread and join with it.
*/
void
c_thread::terminate(void)
{
if (in_context()) {
t_running = false;
pthread_exit(NULL);
} else {
int diag = pthread_cancel(t_thread);
if (diag == ESRCH) {
/* Thread already gone, nothing to do */
} else if (diag != 0) {
t_logger->log("%s Unable to cancel thread: %s\n",
t_thread_name, strerror(diag));
}
void *rval;
diag = pthread_join(t_thread, &rval);
if (diag == ESRCH) {
/* Thread already gone, nothing to do */
} else if (diag != 0) {
t_logger->log("%s Thread join failed: %s\n",
t_thread_name, strerror(diag));
}
t_running = false;
}