vici: Send all queued messages during shutdown

This ensures that e.g. ike/child-updown messages are sent that were
queued but couldn't be sent (even the job to enable to on_write() callback
requires a worker thread that's not around anymore during shutdown).

References #3602.
This commit is contained in:
Tobias Brunner 2020-10-20 20:14:08 +02:00
parent 6586f07162
commit ef636316d2
1 changed files with 24 additions and 4 deletions

View File

@ -310,7 +310,7 @@ static void disconnect(private_vici_socket_t *this, u_int id)
* Write queued output data
*/
static bool do_write(private_vici_socket_t *this, entry_t *entry,
stream_t *stream, char *errmsg, size_t errlen)
stream_t *stream, char *errmsg, size_t errlen, bool block)
{
msg_buf_t *out;
ssize_t len;
@ -321,7 +321,7 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
while (out->hdrlen < sizeof(out->hdr))
{
len = stream->write(stream, out->hdr + out->hdrlen,
sizeof(out->hdr) - out->hdrlen, FALSE);
sizeof(out->hdr) - out->hdrlen, block);
if (len == 0)
{
return FALSE;
@ -343,7 +343,7 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
while (out->buf.len > out->done)
{
len = stream->write(stream, out->buf.ptr + out->done,
out->buf.len - out->done, FALSE);
out->buf.len - out->done, block);
if (len == 0)
{
snprintf(errmsg, errlen, "premature vici disconnect");
@ -383,7 +383,7 @@ CALLBACK(on_write, bool,
entry = find_entry(this, stream, 0, FALSE, TRUE);
if (entry)
{
ret = do_write(this, entry, stream, errmsg, sizeof(errmsg));
ret = do_write(this, entry, stream, errmsg, sizeof(errmsg), FALSE);
if (ret)
{
/* unregister if we have no more messages to send */
@ -656,10 +656,30 @@ METHOD(vici_socket_t, send_, void,
}
}
CALLBACK(flush_messages, void,
entry_t *entry, va_list args)
{
private_vici_socket_t *this;
char errmsg[256] = "";
bool ret;
VA_ARGS_VGET(args, this);
/* no need for any locking as no other threads are running, the connections
* all get disconneted afterwards, so error handling is simple too */
ret = do_write(this, entry, entry->stream, errmsg, sizeof(errmsg), TRUE);
if (!ret && errmsg[0])
{
DBG1(DBG_CFG, errmsg);
}
}
METHOD(vici_socket_t, destroy, void,
private_vici_socket_t *this)
{
DESTROY_IF(this->service);
this->connections->invoke_function(this->connections, flush_messages, this);
this->connections->destroy_function(this->connections, destroy_entry);
this->mutex->destroy(this->mutex);
free(this);