I'm not a contributor to this project, I'm just chiming in.
There's a lot to nitpick in this code snippet and it would be helpful to
see expire_sessions itself. But I think there might be an important
pitfall here. It's not likely that your server is "shutting down". Like
every database I've worked with in my entire life, MySQL has a timeout
to how long a client connection can remain idle before the server
decides to close it. You have the option of increasing that timeout
server-side, but this won't solve your problem. Here are a few
approaches you can take to solve the problem.
* You can create a database connection only when you need it, i.e. do
not maintain a connection pool or keep any connections open when MHD
workers aren't doing anything. This isn't performant or scalable but
it's 100% fault tolerant. Your database can go down, up, disappear and
your web app will persist happily. In this context that would mean you
create and close the connection entirely within expire_sessions, instead
of reusing a connection.
* Or, detect that the reused connection has "gone away" from within
expire_sessions, and deal with it on-the-fly. There are two ways you can
do this:
* Ping the database before you send any MySQL statement. If the ping
fails, throw out the connection and start a new one. Not the most
performant but disputably easier to track/debug.
* Or, send your MySQL statement like you're currently doing, but
detect the error code or really any connection error, throw out the
connection, create a new one, and retry the statement. This is probably
the solution you're looking for but requires a significant refactor if
you're using the MySQL API directly.
Hope that helps!
On 2023-03-12 10:13 am, klemens wrote:
During longer idle-times of the server, when no queries to
mysql happen, mysql is shutting down and the server stops
with the message "mysql server has gone away". I try to
avoid this by making a "select now()" query every hour or
so, but it seems, I can't get out of the eventloop, the
func expire_sessions() where the query is done, is never
called:
MHD_start_daemon ( 0,
55301,
&on_client_connect, myclient_ip,
&create_response, NULL,
MHD_OPTION_NOTIFY_COMPLETED, &expire_sessions, NULL,
MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int)120,
MHD_OPTION_CONNECTION_LIMIT, (unsigned int)50,
MHD_OPTION_END
);
if (NULL == vbad)
return (emsg ("Can't create daemon"));
while (1)
{
expire_sessions ();
max = 0;
FD_ZERO (&rs);
FD_ZERO (&ws);
FD_ZERO (&es);
if (MHD_YES != MHD_get_fdset (vbad, &rs, &ws, &es, &max))
break; /* fatal internal error */
if (MHD_get_timeout (vbad, &mhd_timeout) == MHD_YES)
{
tv.tv_sec = mhd_timeout / 1000;
tv.tv_usec = (mhd_timeout - (tv.tv_sec * 1000)) * 1000;
tvp = &tv;
}
else
tvp = NULL;
if (-1 == select (max + 1, &rs, &ws, &es, tvp))
{
if (EINTR != errno)
abort ();
}
MHD_run (vbad);
Could anyone please point out, what I'm doing wrong here. Thanks in
advanve.
Klemens.