whitelist: Fix deadlock when handling client disconnection
Calling stream_t::destroy from the stream_t::on_read callback will block the thread in watcher_t::remove because the FD is currently "in callback". A similar issue was fixed in the lookip plugin with961409b668("lookip: Disconnect asynchronously to avoid dead-locking watcher unregistration"). Fixes:85ebf6abd4("whitelist: Add error handling to socket reads and fix a memory leak")
This commit is contained in:
committed by
Tobias Brunner
parent
8a6f9ba70e
commit
14cbe0bf24
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <collections/linked_list.h>
|
#include <collections/linked_list.h>
|
||||||
|
#include <processing/jobs/callback_job.h>
|
||||||
|
|
||||||
#include "whitelist_msg.h"
|
#include "whitelist_msg.h"
|
||||||
|
|
||||||
@@ -101,6 +102,40 @@ typedef struct {
|
|||||||
size_t read;
|
size_t read;
|
||||||
} whitelist_conn_t;
|
} whitelist_conn_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information needed for async disconnect job.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
whitelist_conn_t *conn;
|
||||||
|
stream_t *stream;
|
||||||
|
} disconnect_data_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronous callback to disconnect client
|
||||||
|
*/
|
||||||
|
CALLBACK(disconnect_async, job_requeue_t,
|
||||||
|
disconnect_data_t *data)
|
||||||
|
{
|
||||||
|
data->stream->destroy(data->stream);
|
||||||
|
free(data->conn);
|
||||||
|
return JOB_REQUEUE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnect a connected client
|
||||||
|
*/
|
||||||
|
static void disconnect(whitelist_conn_t *conn, stream_t *stream)
|
||||||
|
{
|
||||||
|
disconnect_data_t *data;
|
||||||
|
|
||||||
|
INIT(data,
|
||||||
|
.conn = conn,
|
||||||
|
.stream = stream,
|
||||||
|
);
|
||||||
|
lib->processor->queue_job(lib->processor,
|
||||||
|
(job_t*)callback_job_create(disconnect_async, data, free, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatch a received message
|
* Dispatch a received message
|
||||||
*/
|
*/
|
||||||
@@ -127,8 +162,7 @@ CALLBACK(on_read, bool,
|
|||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "whitelist socket error: %s", strerror(errno));
|
DBG1(DBG_CFG, "whitelist socket error: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
stream->destroy(stream);
|
disconnect(conn, stream);
|
||||||
free(conn);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
conn->read += len;
|
conn->read += len;
|
||||||
|
|||||||
Reference in New Issue
Block a user