Skip to content

Commit e216537

Browse files
author
Marius Sturm
committed
catch sigpipe on vanished gelf connection
1 parent 2387940 commit e216537

File tree

2 files changed

+79
-63
lines changed

2 files changed

+79
-63
lines changed

src/apache20.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "apr_hash.h"
77
#include "apr_optional.h"
88
#include "apr_reslist.h"
9+
#include "apr_signal.h"
910
#define APR_WANT_STRFUNC
1011
#include "apr_want.h"
1112
#include "apr_tables.h"

src/mod_log_gelf.c

Lines changed: 78 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
#define DEFAULT_LOG_FMT "ABDhmsvRti"
1818
#define UDP 0
1919
#define TCP 1
20-
#define RECONNECT_INTERVAL 500000
20+
#define RECONNECT_INTERVAL 120000000
2121
#define MIN_CONNECTIONS 1
2222
#define MAX_CONNECTIONS 5
2323
#define SEND_BUFFER 1048576
2424

2525
module AP_MODULE_DECLARE_DATA log_gelf_module;
2626

27-
static int verbose = 0;
27+
static int verbose = 1;
2828
static char errbuf[1024];
2929

3030
typedef struct {
@@ -35,26 +35,26 @@ typedef struct {
3535
} log_item;
3636

3737
typedef struct {
38-
apr_socket_t *s; /* Actual GELF connection */
39-
apr_sockaddr_t *sa; /* GELF Address */
38+
apr_socket_t *s; /* Actual GELF connection */
39+
apr_sockaddr_t *sa; /* GELF Address */
4040
} gelf_connection;
4141

4242
typedef struct {
43-
int enabled;
44-
int port; /* GELF port */
45-
int protocol; /* 0=UDP 1=TCP */
46-
const char *server; /* Hostname/IP of Graylog server */
47-
const char *source; /* Source field */
48-
const char *facility; /* Facility field */
49-
const char *tag; /* Optional tag field */
50-
const char *fields; /* String with fields of interest */
51-
const char *cookie; /* Log this cookie */
52-
log_item **parsed_fields; /* Link fields to extractor function */
53-
apr_pool_t *parse_pool; /* memory pool for option parsing */
54-
apr_reslist_t *connection_pool;
55-
int nmin;
56-
int nkeep;
57-
int nmax;
43+
int enabled;
44+
int port; /* GELF port */
45+
int protocol; /* 0=UDP 1=TCP */
46+
const char *server; /* Hostname/IP of Graylog server */
47+
const char *source; /* Source field */
48+
const char *facility; /* Facility field */
49+
const char *tag; /* Optional tag field */
50+
const char *fields; /* String with fields of interest */
51+
const char *cookie; /* Log this cookie */
52+
log_item **parsed_fields; /* Link fields to extractor function */
53+
apr_pool_t *parse_pool; /* memory pool for option parsing */
54+
apr_reslist_t *connection_pool; /* Connection pool, with min, max and ttl settings */
55+
int nmin;
56+
int nkeep;
57+
int nmax;
5858
apr_interval_time_t ttl;
5959
} gelf_config;
6060

@@ -66,7 +66,7 @@ static void *create_gelf_configuration(apr_pool_t *pool, server_rec *server) {
6666
config->source = "localhost";
6767
config->facility = "apache-gelf";
6868
config->fields = DEFAULT_LOG_FMT;
69-
/* connection pool settings */
69+
/* connection pool settings */
7070
config->nmin = MIN_CONNECTIONS;
7171
config->nkeep = MIN_CONNECTIONS;
7272
config->nmax = MAX_CONNECTIONS;
@@ -197,34 +197,34 @@ static const command_rec log_gelf_directives[] = {
197197
static gelf_connection* log_gelf_connection_acquire(request_rec* r) {
198198
gelf_config* config = ap_get_module_config(r->server->module_config, &log_gelf_module) ;
199199
apr_status_t rv;
200-
gelf_connection *con;
201-
200+
gelf_connection *con;
201+
202202
rv = apr_reslist_acquire(config->connection_pool, (void**)&con);
203-
if ( rv != APR_SUCCESS ) {
203+
if (rv != APR_SUCCESS || !con) {
204204
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
205205
"mod_log_gelf: Failed to acquire GELF connection from pool %s",
206206
apr_strerror(rv, errbuf, sizeof(errbuf)));
207207
return NULL;
208208
}
209-
209+
210210
return con;
211211
}
212212

213213
static apr_status_t log_gelf_connection_release(request_rec* r, gelf_connection *con) {
214-
gelf_config* config = ap_get_module_config(r->server->module_config, &log_gelf_module);
215-
apr_status_t rv;
216-
rv = apr_reslist_release(config->connection_pool, con);
217-
if (rv != APR_SUCCESS) {
218-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_log_gelf: Can not release GELF socket.");
219-
}
220-
221-
return rv;
214+
gelf_config* config = ap_get_module_config(r->server->module_config, &log_gelf_module);
215+
apr_status_t rv;
216+
rv = apr_reslist_release(config->connection_pool, con);
217+
if (rv != APR_SUCCESS) {
218+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_log_gelf: Can not release GELF socket.");
219+
}
220+
221+
return rv;
222222
}
223223

224224
static apr_status_t log_gelf_get_gelf_connection(gelf_connection *gc, gelf_config *config, apr_pool_t *pool) {
225225
apr_status_t rv;
226226
int proto = NULL;
227-
int type = NULL;
227+
int type = NULL;
228228

229229
if (config->protocol == TCP) {
230230
proto = APR_PROTO_TCP;
@@ -298,20 +298,20 @@ static apr_status_t log_gelf_get_gelf_connection(gelf_connection *gc, gelf_confi
298298
static apr_status_t gelf_pool_construct(void** rs, void* params, apr_pool_t* pool) {
299299
gelf_config *config = (gelf_config*)params;
300300
apr_status_t rv;
301-
302-
if (config->enabled < 1) {
303-
/* module disabled, no socket needed */
304-
return APR_SUCCESS;
305-
}
306-
301+
302+
if (config->enabled < 1) {
303+
/* module disabled, no socket needed */
304+
return APR_SUCCESS;
305+
}
306+
307307
if (verbose > 0) {
308308
ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, pool, "mod_log_gelf: Creating new socket for pool: %s:%d",
309309
config->server, config->port);
310310
}
311311

312-
gelf_connection *con;
313-
con = apr_palloc(pool, sizeof(gelf_connection));
314-
rv = log_gelf_get_gelf_connection(con, config, pool);
312+
gelf_connection *con;
313+
con = apr_palloc(pool, sizeof(gelf_connection));
314+
rv = log_gelf_get_gelf_connection(con, config, pool);
315315
if (rv != APR_SUCCESS) {
316316
return APR_EGENERAL;
317317
}
@@ -326,18 +326,21 @@ static apr_status_t gelf_pool_construct(void** rs, void* params, apr_pool_t* poo
326326
}
327327

328328
static apr_status_t gelf_pool_destruct(void* resource, void* params, apr_pool_t* pool) {
329-
if (resource) {
330-
gelf_connection *con = (gelf_connection*)resource;
331-
apr_socket_close(con->s);
332-
}
329+
if (resource) {
330+
if (verbose > 0) {
331+
ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, pool, "mod_log_gelf: Removing socket from pool");
332+
}
333+
gelf_connection *con = (gelf_connection*)resource;
334+
apr_socket_close(con->s);
335+
}
333336
return APR_SUCCESS ;
334337
}
335338

336339
/* Registered hooks */
337340
static int log_gelf_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *server) {
338341
gelf_config *config = ap_get_module_config(server->module_config, &log_gelf_module);
339342

340-
/* initialize resource list to keep track of socket pool */
343+
/* initialize resource list to keep track of socket pool */
341344
if ( apr_reslist_create(&config->connection_pool,
342345
config->nmin,
343346
config->nkeep,
@@ -347,8 +350,8 @@ static int log_gelf_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *pte
347350
gelf_pool_destruct,
348351
config, p) != APR_SUCCESS ) {
349352
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, server, "mod_log_gelf: Failed to initialize resource pool, disabling GELF logging.");
350-
config->enabled = 0;
351-
return OK;
353+
config->enabled = 0;
354+
return OK;
352355
}
353356
apr_pool_cleanup_register(p, config->connection_pool,
354357
(void*)apr_reslist_destroy, apr_pool_cleanup_null);
@@ -394,7 +397,7 @@ static int log_gelf_transaction(request_rec *request) {
394397
"mod_log_gelf: Module is disbaled, not sending log data!");
395398
return OK;
396399
}
397-
400+
398401
/* skip logging if endpoint is not configured properly */
399402
if (!config->server || !config->port) {
400403
log_error(APLOG_MARK, APLOG_ERR, 0, request->server,
@@ -532,14 +535,14 @@ void log_gelf_send_message_udp(const transferData* payload, request_rec *request
532535
} else {
533536
log_error(APLOG_MARK, APLOG_ERR, 0, request->server,
534537
"mod_log_gelf: Got empty log message, not sending anything.");
535-
return;
538+
return;
536539
}
537540

538-
/* acquire a free socket, send message, release socket */
541+
/* acquire a free socket, send message, release socket */
539542
gelf_connection *con = log_gelf_connection_acquire(request);
540-
if (!con) {
541-
return;
542-
}
543+
if (!con) {
544+
return;
545+
}
543546

544547
if (verbose > 0) {
545548
log_error(APLOG_MARK, APLOG_ERR, 0, request->server,
@@ -553,7 +556,7 @@ void log_gelf_send_message_udp(const transferData* payload, request_rec *request
553556
payload->size, apr_strerror(rv, errbuf, sizeof(errbuf)));
554557
}
555558

556-
log_gelf_connection_release(request, con);
559+
log_gelf_connection_release(request, con);
557560
}
558561

559562
void log_gelf_send_message_tcp(const transferData* payload, request_rec *request) {
@@ -573,11 +576,11 @@ void log_gelf_send_message_tcp(const transferData* payload, request_rec *request
573576
/* copy payload and append '\0' */
574577
const char* gelf_payload = apr_pstrmemdup(request->pool, payload->data, payload->size);
575578

576-
/* acquire a free socket, send message, release socket */
579+
/* acquire a free socket, send message, release socket */
577580
gelf_connection *con = log_gelf_connection_acquire(request);
578-
if (!con) {
579-
return;
580-
}
581+
if (!con || !con->s) {
582+
return;
583+
}
581584

582585
if (verbose > 0) {
583586
log_error(APLOG_MARK, APLOG_ERR, 0, request->server,
@@ -589,16 +592,26 @@ void log_gelf_send_message_tcp(const transferData* payload, request_rec *request
589592
log_error(APLOG_MARK, APLOG_ERR, 0, request->server,
590593
"mod_log_gelf: Error writing to socket %d bytes. Error %s",
591594
payload->size, apr_strerror(rv, errbuf, sizeof(errbuf)));
592-
apr_reslist_invalidate(config->connection_pool, con) ;
595+
apr_reslist_invalidate(config->connection_pool, con) ;
593596
}
594-
595-
log_gelf_connection_release(request, con);
597+
598+
log_gelf_connection_release(request, con);
596599
}
597600

598601
double log_gelf_get_timestamp() {
599602
return ((double) (apr_time_now() / 1000)) / 1000.0;
600603
}
601604

605+
static void log_gelf_sig_pipe(int sig){
606+
apr_pool_t *pool = NULL;
607+
apr_pool_create(&pool, NULL);
608+
609+
if (verbose > 0) {
610+
ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool,
611+
"mod_log_gelf: Got signal SIGPIPE. Most likely GELF server went away.");
612+
}
613+
}
614+
602615
static void log_gelf_child_init(apr_pool_t *p, server_rec *server) {
603616
apr_status_t rv;
604617
gelf_config *config = ap_get_module_config(server->module_config, &log_gelf_module);
@@ -614,6 +627,8 @@ static void log_gelf_child_init(apr_pool_t *p, server_rec *server) {
614627
gelf_config *config = create_gelf_configuration(p, server);
615628
ap_set_module_config(server->module_config, &log_gelf_module, config);
616629
}
630+
631+
apr_signal(SIGPIPE, log_gelf_sig_pipe);
617632
}
618633

619634
static void register_hooks(apr_pool_t *p) {

0 commit comments

Comments
 (0)