Skip to content

Commit 751e6b9

Browse files
erainedsiper
authored andcommitted
out_stackdriver: clean up oauth2 cache lifecycle
Track oauth2 cache init with a refcounted lock and release it on init failures and plugin exit, so pthread keys are not leaked. Guard token mutex cleanup to avoid destroying uninitialized locks. Signed-off-by: Yu Yi <[email protected]>
1 parent 06bcb8a commit 751e6b9

File tree

3 files changed

+101
-16
lines changed

3 files changed

+101
-16
lines changed

plugins/out_stackdriver/stackdriver.c

Lines changed: 94 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ pthread_key_t oauth2_type;
5050
pthread_key_t oauth2_token;
5151
pthread_key_t oauth2_token_expires;
5252

53+
static int oauth2_cache_initialized = FLB_FALSE;
54+
static int oauth2_cache_users = 0;
55+
static pthread_mutex_t oauth2_cache_lock = PTHREAD_MUTEX_INITIALIZER;
56+
5357
static void oauth2_cache_exit(void *ptr)
5458
{
5559
if (ptr) {
@@ -64,12 +68,60 @@ static void oauth2_cache_free_expiration(void *ptr)
6468
}
6569
}
6670

67-
static void oauth2_cache_init()
71+
static int oauth2_cache_init()
6872
{
69-
/* oauth2 pthread key */
70-
pthread_key_create(&oauth2_type, oauth2_cache_exit);
71-
pthread_key_create(&oauth2_token, oauth2_cache_exit);
72-
pthread_key_create(&oauth2_token_expires, oauth2_cache_free_expiration);
73+
int ret;
74+
75+
ret = 0;
76+
77+
pthread_mutex_lock(&oauth2_cache_lock);
78+
79+
if (oauth2_cache_initialized == FLB_FALSE) {
80+
/* oauth2 pthread key */
81+
ret = pthread_key_create(&oauth2_type, oauth2_cache_exit);
82+
if (ret != 0) {
83+
goto done;
84+
}
85+
ret = pthread_key_create(&oauth2_token, oauth2_cache_exit);
86+
if (ret != 0) {
87+
pthread_key_delete(oauth2_type);
88+
goto done;
89+
}
90+
ret = pthread_key_create(&oauth2_token_expires,
91+
oauth2_cache_free_expiration);
92+
if (ret != 0) {
93+
pthread_key_delete(oauth2_type);
94+
pthread_key_delete(oauth2_token);
95+
goto done;
96+
}
97+
oauth2_cache_initialized = FLB_TRUE;
98+
}
99+
100+
if (ret == 0) {
101+
oauth2_cache_users++;
102+
}
103+
104+
done:
105+
pthread_mutex_unlock(&oauth2_cache_lock);
106+
return ret;
107+
}
108+
109+
static void oauth2_cache_cleanup(void)
110+
{
111+
pthread_mutex_lock(&oauth2_cache_lock);
112+
113+
if (oauth2_cache_users > 0) {
114+
oauth2_cache_users--;
115+
if (oauth2_cache_users == 0 &&
116+
oauth2_cache_initialized == FLB_TRUE) {
117+
pthread_key_delete(oauth2_type);
118+
pthread_key_delete(oauth2_token);
119+
pthread_key_delete(oauth2_token_expires);
120+
oauth2_cache_initialized = FLB_FALSE;
121+
}
122+
}
123+
124+
pthread_mutex_unlock(&oauth2_cache_lock);
73125
}
74126

75127
/* Set oauth2 type and token in pthread keys */
@@ -1221,7 +1273,7 @@ static int cb_stackdriver_init(struct flb_output_instance *ins,
12211273
/* Load config map */
12221274
ret = flb_output_config_map_set(ins, (void *) ctx);
12231275
if (ret == -1) {
1224-
return -1;
1276+
goto error;
12251277
}
12261278

12271279
/* Set context */
@@ -1237,10 +1289,20 @@ static int cb_stackdriver_init(struct flb_output_instance *ins,
12371289
}
12381290

12391291
/* Initialize oauth2 cache pthread keys */
1240-
oauth2_cache_init();
1292+
ret = oauth2_cache_init();
1293+
if (ret != 0) {
1294+
flb_plg_error(ins, "failed to initialize oauth2 cache");
1295+
goto error;
1296+
}
1297+
ctx->oauth2_cache_acquired = FLB_TRUE;
12411298

12421299
/* Create mutex for acquiring oauth tokens (they are shared across flush coroutines) */
1243-
pthread_mutex_init(&ctx->token_mutex, NULL);
1300+
ret = pthread_mutex_init(&ctx->token_mutex, NULL);
1301+
if (ret != 0) {
1302+
flb_plg_error(ins, "failed to initialize token mutex");
1303+
goto error;
1304+
}
1305+
ctx->token_mutex_initialized = FLB_TRUE;
12441306

12451307
/* Create Upstream context for Stackdriver Logging (no oauth2 service) */
12461308
ctx->u = flb_upstream_create_url(config, ctx->cloud_logging_write_url,
@@ -1253,15 +1315,15 @@ static int cb_stackdriver_init(struct flb_output_instance *ins,
12531315

12541316
if (!ctx->u) {
12551317
flb_plg_error(ctx->ins, "upstream creation failed");
1256-
return -1;
1318+
goto error;
12571319
}
12581320
if (!ctx->metadata_u) {
12591321
flb_plg_error(ctx->ins, "metadata upstream creation failed");
1260-
return -1;
1322+
goto error;
12611323
}
12621324
if (!ctx->o) {
12631325
flb_plg_error(ctx->ins, "cannot create oauth2 context");
1264-
return -1;
1326+
goto error;
12651327
}
12661328
flb_output_upstream_set(ctx->u, ins);
12671329

@@ -1282,27 +1344,27 @@ static int cb_stackdriver_init(struct flb_output_instance *ins,
12821344
if (ctx->metadata_server_auth) {
12831345
ret = gce_metadata_read_project_id(ctx);
12841346
if (ret == -1) {
1285-
return -1;
1347+
goto error;
12861348
}
12871349

12881350
if (ctx->resource_type != RESOURCE_TYPE_GENERIC_NODE
12891351
&& ctx->resource_type != RESOURCE_TYPE_GENERIC_TASK) {
12901352
ret = gce_metadata_read_zone(ctx);
12911353
if (ret == -1) {
1292-
return -1;
1354+
goto error;
12931355
}
12941356

12951357
ret = gce_metadata_read_instance_id(ctx);
12961358
if (ret == -1) {
1297-
return -1;
1359+
goto error;
12981360
}
12991361
}
13001362
}
13011363

13021364
/* Validate project_id */
13031365
if (!ctx->project_id) {
13041366
flb_plg_error(ctx->ins, "property 'project_id' is not set");
1305-
return -1;
1367+
goto error;
13061368
}
13071369

13081370
if (!ctx->export_to_project_id) {
@@ -1312,10 +1374,22 @@ static int cb_stackdriver_init(struct flb_output_instance *ins,
13121374
ret = flb_stackdriver_regex_init(ctx);
13131375
if (ret == -1) {
13141376
flb_plg_error(ctx->ins, "failed to init stackdriver custom regex");
1315-
return -1;
1377+
goto error;
13161378
}
13171379

13181380
return 0;
1381+
1382+
error:
1383+
if (ctx->token_mutex_initialized == FLB_TRUE) {
1384+
pthread_mutex_destroy(&ctx->token_mutex);
1385+
ctx->token_mutex_initialized = FLB_FALSE;
1386+
}
1387+
if (ctx->oauth2_cache_acquired == FLB_TRUE) {
1388+
oauth2_cache_cleanup();
1389+
ctx->oauth2_cache_acquired = FLB_FALSE;
1390+
}
1391+
flb_stackdriver_conf_destroy(ctx);
1392+
return -1;
13191393
}
13201394

13211395
static int validate_severity_level(severity_t * s,
@@ -3087,6 +3161,10 @@ static int cb_stackdriver_exit(void *data, struct flb_config *config)
30873161
return -1;
30883162
}
30893163

3164+
if (ctx->oauth2_cache_acquired == FLB_TRUE) {
3165+
oauth2_cache_cleanup();
3166+
ctx->oauth2_cache_acquired = FLB_FALSE;
3167+
}
30903168
flb_stackdriver_conf_destroy(ctx);
30913169
return 0;
30923170
}

plugins/out_stackdriver/stackdriver.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,12 @@ struct flb_stackdriver {
202202
/* environment variable settings */
203203
struct flb_stackdriver_env *env;
204204

205+
/* oauth2 cache reference */
206+
int oauth2_cache_acquired;
207+
205208
/* mutex for acquiring oauth tokens */
206209
pthread_mutex_t token_mutex;
210+
int token_mutex_initialized;
207211

208212
/* upstream context for stackdriver write end-point */
209213
struct flb_upstream *u;

plugins/out_stackdriver/stackdriver_conf.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,9 @@ int flb_stackdriver_conf_destroy(struct flb_stackdriver *ctx)
706706

707707
flb_kv_release(&ctx->config_labels);
708708
flb_kv_release(&ctx->resource_labels_kvs);
709+
if (ctx->token_mutex_initialized) {
710+
pthread_mutex_destroy(&ctx->token_mutex);
711+
}
709712
flb_free(ctx);
710713

711714
return 0;

0 commit comments

Comments
 (0)