Usually, you will eventually find that you do need to wait on the thread
to finish for a controlled shutdown, and at that point it is then better
to keep the thread handles in some data structure so you can join. At
least I found that to be virtually always the case when doing
disciplined multi-threaded programming. But, this is certainly not
fundamental, and you might be able to write perfectly correct programs
with detached threads.
Your existing approach, for example, does not seem to naturally support
a clean shutdown of the process using CTRL-C / SIGTERM.
The CTRL-C / SIGTERM will be required by the application, so after this advice, I'm going to use a list with mutex and join (or cancel) the active threads before shutting down the server.
Supposing this new design, what is the best point to call the "resume" function? For example:
static void *thread_cb(void *cls) {
/* this is inside new thread */
struct req *r = cls;
// MHD_resume_connection(r->con); // position 1
r->cb(); // possible long time processing data
MHD_resume_connection(r->con); // position 2
return NULL;
}
int ahc(...) {
...
MHD_suspend_connection(r->con);
ret = pthread_create(&thread, NULL, thread_cb, r);
MHD_resume_connection(r->con);
return ret;
}
I realized it must be called at position 2, i.e after the data processing. BTW at position 1 would be nice to ensure resuming connection before processing any data, however, it may lock the server, since hard/blocking data processing is back to the main event loop.
Is my way of thinking correct? 🤔
--