Http_unix_daemon with threads

My program (webservice with http_unix_daemon) does a quite a bit of expensive initialization at startup. As a consequence, waiting time is long until the server is ready. However, about 90% of this expensive initialization can actually be postponed to later periods when the server is idle.

I thought that I just create some threads at initialization that “thread_wait” until they receive an idle signal. They also use a mutex so that the necessary work is done one after the other. Now, with http_unix_deamon, I get a

No permission to fork process `main' (running_threads([<thread>(3,0x584137e4cda0), ...

How can I implement this properly? And: is this a good idea at all?

I would suspect this happens because http_unix_daemon works by double-forking to daemonize the process and threads don’t really work in conjunction with forking (because forking copies the process but only with the current thread, not any others, potentially leaving mutexes in invalid states - in general, it’s not safe to combine the two). I’ve never used the daemonize library, but I guess either set up the thread creation to run after daemonizing or run the webservice directly and have it backgrounded by making it a systemd service or similar (instead of having it daemonize itself).

1 Like

Whether it is a good idea or not depends on what you want. The default is to fork() indeed and do old-style Unix daemonize. That indeed blocks creeting threads before. These days you typically run services under systemd or inside a Docker container and you use --no-fork.

For such things it uses broadcast/1 to indicate two events. From the manual:

  • http(pre_server_start)
    Run after fork, just before starting the HTTP server. Can be used
    to load additional files or perform additional initialisation, such as
    starting additional threads. Recall that it is not possible to start
    threads before forking.

  • http(post_server_start)
    Run after starting the HTTP server.

So, you do something like this:

:- listen(http(pre_server_start), do_my_things).

For example, the ClioPatria RDF service uses this to load the RDF in the background and reply to all HTTP requests that it is loading the database (and how much it progressed) until all data is ready.

1 Like

Works perfectly with the broadcast, thank you.

Impressive.