Skip to content

Commit 4d1f11a

Browse files
authored
Merge pull request #2204 from evgenyz/sync
Fix thread syncronization problems
2 parents a954d9d + 7a9b7a9 commit 4d1f11a

File tree

10 files changed

+45
-33
lines changed

10 files changed

+45
-33
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ if (MSVC)
529529
endif()
530530

531531
if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
532-
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -W -Wall -Wnonnull -Wshadow -Wformat -Wundef -Wno-unused-parameter -Wmissing-prototypes -Wno-unknown-pragmas -Wno-int-conversion -Werror=implicit-function-declaration -D_GNU_SOURCE -std=c99")
532+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -W -Wall -Wnonnull -Wshadow -Wformat -Wundef -Wno-unused-parameter -Wmissing-prototypes -Wno-unknown-pragmas -Wno-int-conversion -Werror=implicit-function-declaration -D_GNU_SOURCE -DRBT_IMPLICIT_LOCKING=1 -std=c99")
533533
add_link_options(-Wl,-z,now)
534534
endif()
535535
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")

src/OVAL/probes/SEAP/seap-command.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ static SEXP_t *__SEAP_cmd_sync_handler (SEXP_t *res, void *arg)
205205
h->args = res;
206206
(void) pthread_mutex_lock (&h->mtx);
207207
h->signaled = 1;
208-
(void) pthread_cond_signal (&h->cond);
208+
(void) pthread_cond_broadcast (&h->cond);
209209
(void) pthread_mutex_unlock (&h->mtx);
210210

211211
return (NULL);
@@ -322,9 +322,6 @@ SEXP_t *SEAP_cmd_exec (SEAP_CTX_t *ctx,
322322
h.args = NULL;
323323
h.signaled = 0;
324324

325-
if (pthread_mutex_lock (&(h.mtx)) != 0)
326-
abort ();
327-
328325
rec = SEAP_cmdrec_new ();
329326
rec->code = cmdptr->id;
330327
rec->func = &__SEAP_cmd_sync_handler;
@@ -377,8 +374,6 @@ SEXP_t *SEAP_cmd_exec (SEAP_CTX_t *ctx,
377374
timeout.tv_nsec = 0;
378375
*/
379376
for (;;) {
380-
pthread_mutex_unlock(&h.mtx);
381-
382377
if (SEAP_packet_recv(ctx, sd, &packet_rcv) != 0) {
383378
dD("FAIL: ctx=%p, sd=%d, errno=%u, %s.", ctx, sd, errno, strerror(errno));
384379
SEAP_packet_free(packet);
@@ -407,21 +402,23 @@ SEXP_t *SEAP_cmd_exec (SEAP_CTX_t *ctx,
407402
}
408403

409404
/* Morbo: THIS IS NOT HOW SYCHNRONIZATION WORKS! */
410-
if (h.signaled)
405+
if (h.signaled) {
406+
h.signaled = 0;
411407
break;
408+
}
412409
}
413410
} else {
414411
/*
415412
* Someone else does receiving of events for us.
416413
* Just wait for the condition to be signaled.
417414
*/
418-
if (pthread_cond_wait(&h.cond, &h.mtx) != 0) {
419-
/*
420-
* Fatal error - don't know how to handle
421-
* this so let's just call abort()...
422-
*/
423-
abort();
424-
}
415+
pthread_mutex_lock(&h.mtx);
416+
while (!h.signaled) {
417+
pthread_cond_wait(&h.cond, &h.mtx);
418+
}
419+
// This might not be needed, but still
420+
h.signaled = 0;
421+
pthread_mutex_unlock(&h.mtx);
425422
}
426423

427424
dD("cond return: h.args=%p", h.args);
@@ -436,7 +433,6 @@ SEXP_t *SEAP_cmd_exec (SEAP_CTX_t *ctx,
436433
/*
437434
* SEAP_cmdtbl_del(dsc->cmd_w_table, rec);
438435
*/
439-
pthread_mutex_unlock (&(h.mtx));
440436
pthread_cond_destroy (&(h.cond));
441437
pthread_mutex_destroy (&(h.mtx));
442438
SEAP_packet_free(packet);

src/OVAL/probes/SEAP/seap-packet.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,14 @@ static int SEAP_packet_sexp2msg (SEXP_t *sexp_msg, SEAP_msg_t *seap_msg)
206206
_A(attr_i >= (SEXP_list_length (sexp_msg) - 4)/2);
207207

208208
seap_msg->attrs_cnt = attr_i;
209-
void *new_attrs = realloc(seap_msg->attrs, sizeof(SEAP_attr_t) * seap_msg->attrs_cnt);
210-
if (new_attrs != NULL || seap_msg->attrs_cnt == 0)
209+
if (seap_msg->attrs_cnt == 0) {
210+
free(seap_msg->attrs);
211+
seap_msg->attrs = NULL;
212+
} else {
213+
void *new_attrs = realloc(seap_msg->attrs, sizeof(SEAP_attr_t) * seap_msg->attrs_cnt);
211214
seap_msg->attrs = new_attrs;
215+
}
216+
212217
seap_msg->sexp = SEXP_list_last (sexp_msg);
213218

214219
return (0);

src/OVAL/probes/probe/icache.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ const char* thread_name = "icache_worker";
201201
pair = &pair_mem;
202202
dD("icache worker ready");
203203

204-
switch (errno = pthread_barrier_wait(&OSCAP_GSYM(th_barrier)))
204+
switch (errno = pthread_barrier_wait(cache->th_barrier))
205205
{
206206
case 0:
207207
case PTHREAD_BARRIER_SERIAL_THREAD:
@@ -309,7 +309,7 @@ const char* thread_name = "icache_worker";
309309
return (NULL);
310310
}
311311

312-
probe_icache_t *probe_icache_new(void)
312+
probe_icache_t *probe_icache_new(pthread_barrier_t *th_barrier)
313313
{
314314
probe_icache_t *cache = malloc(sizeof(probe_icache_t));
315315
cache->tree = rbt_i64_new();
@@ -323,6 +323,7 @@ probe_icache_t *probe_icache_new(void)
323323
cache->queue_end = 0;
324324
cache->queue_cnt = 0;
325325
cache->queue_max = PROBE_IQUEUE_CAPACITY;
326+
cache->th_barrier = th_barrier;
326327

327328
if (pthread_cond_init(&cache->queue_notempty, NULL) != 0) {
328329
dE("Can't initialize icache queue condition variable (notempty): %u, %s",

src/OVAL/probes/probe/icache.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <stddef.h>
2626
#include <sexp.h>
2727
#include "../SEAP/generic/rbt/rbt.h"
28+
#include "common/compat_pthread_barrier.h"
2829

2930
#ifndef PROBE_IQUEUE_CAPACITY
3031
#define PROBE_IQUEUE_CAPACITY 1024
@@ -41,6 +42,7 @@ typedef struct {
4142
typedef struct {
4243
rbt_t *tree; /* XXX: rewrite to extensible or linear hashing */
4344
pthread_t thid;
45+
pthread_barrier_t *th_barrier;
4446

4547
pthread_mutex_t queue_mutex;
4648
pthread_cond_t queue_notempty;
@@ -58,7 +60,7 @@ typedef struct {
5860
uint16_t count;
5961
} probe_citem_t;
6062

61-
probe_icache_t *probe_icache_new(void);
63+
probe_icache_t *probe_icache_new(pthread_barrier_t *th_barrier);
6264
int probe_icache_add(probe_icache_t *cache, SEXP_t *cobj, SEXP_t *item);
6365
int probe_icache_nop(probe_icache_t *cache);
6466
void probe_icache_free(probe_icache_t *cache);

src/OVAL/probes/probe/input_handler.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void *probe_input_handler(void *arg)
8585

8686
pthread_cleanup_push(pthread_attr_cleanup_handler, (void *)&pth_attr);
8787

88-
switch (errno = pthread_barrier_wait(&OSCAP_GSYM(th_barrier)))
88+
switch (errno = pthread_barrier_wait(probe->th_barrier))
8989
{
9090
case 0:
9191
case PTHREAD_BARRIER_SERIAL_THREAD:

src/OVAL/probes/probe/probe.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ typedef struct {
6666

6767
pthread_t th_input;
6868
pthread_t th_signal;
69+
pthread_barrier_t *th_barrier;
6970

7071
rbt_t *workers;
7172
uint32_t max_threads;
@@ -105,6 +106,4 @@ typedef enum {
105106
PROBE_OFFLINE_ALL = 0x0f
106107
} probe_offline_flags;
107108

108-
extern pthread_barrier_t OSCAP_GSYM(th_barrier);
109-
110109
#endif /* PROBE_H */

src/OVAL/probes/probe/probe_main.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ bool OSCAP_GSYM(varref_handling) = true;
7171
char **OSCAP_GSYM(no_varref_ents) = NULL;
7272
size_t OSCAP_GSYM(no_varref_ents_cnt) = 0;
7373

74-
pthread_barrier_t OSCAP_GSYM(th_barrier);
75-
7674
extern probe_ncache_t *OSCAP_GSYM(ncache);
7775

7876
static int probe_optecmp(char **a, char **b)
@@ -191,8 +189,10 @@ void *probe_common_main(void *arg)
191189

192190
dD("probe_common_main started");
193191

192+
pthread_barrier_t barrier;
193+
194194
const unsigned thread_count = 2; // input and icache threads
195-
if ((errno = pthread_barrier_init(&OSCAP_GSYM(th_barrier), NULL, thread_count)) != 0) {
195+
if ((errno = pthread_barrier_init(&barrier, NULL, thread_count)) != 0) {
196196
fail(errno, "pthread_barrier_init", __LINE__ - 6);
197197
}
198198

@@ -218,9 +218,10 @@ void *probe_common_main(void *arg)
218218
* Initialize result & name caching
219219
*/
220220
probe.rcache = probe_rcache_new();
221-
probe.icache = probe_icache_new();
221+
probe.icache = probe_icache_new(&barrier);
222222
probe_ncache_clear(OSCAP_GSYM(ncache));
223223
probe.ncache = OSCAP_GSYM(ncache);
224+
probe.th_barrier = &barrier;
224225

225226
/*
226227
* Initialize probe option handlers
@@ -266,5 +267,7 @@ void *probe_common_main(void *arg)
266267

267268
pthread_cleanup_pop(1);
268269

270+
pthread_barrier_destroy(&barrier);
271+
269272
return NULL;
270273
}

src/OVAL/probes/probe/worker.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ static void preload_libraries_before_chroot()
7272
pthread_join(t, NULL);
7373
}
7474

75+
static void pthread_pair_cleanup_handler(void *arg)
76+
{
77+
probe_pwpair_t *pair = (probe_pwpair_t *)arg;
78+
dW("Probe worker thread finished unxpectedly, trying to avoid deadlock now...");
79+
SEAP_replyerr(pair->probe->SEAP_ctx, pair->probe->sd, pair->pth->msg, -100);
80+
}
81+
7582
void *probe_worker_runfn(void *arg)
7683
{
7784
dD("probe_worker_runfn has started");
@@ -88,6 +95,8 @@ void *probe_worker_runfn(void *arg)
8895
# endif
8996
#endif
9097
dD("handling SEAP message ID %u", pair->pth->sid);
98+
pthread_cleanup_push(pthread_pair_cleanup_handler, (void *)pair);
99+
91100
//
92101
probe_ret = -1;
93102
probe_res = pair->pth->msg_handler(pair->probe, pair->pth->msg, &probe_ret);
@@ -172,6 +181,8 @@ void *probe_worker_runfn(void *arg)
172181
free(pair);
173182
pthread_detach(pthread_self());
174183

184+
pthread_cleanup_pop(0);
185+
175186
dD("probe_worker_runfn has finished");
176187
return (NULL);
177188
}

src/common/oscap_pcre.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ oscap_pcre_t *oscap_pcre_compile(const char *pattern, oscap_pcre_options_t optio
106106
int errno;
107107
PCRE2_SIZE erroffset2;
108108
res->re_ctx = NULL;
109-
dD("pcre2_compile_8: patt=%s", pattern);
110109
res->re = pcre2_compile_8((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, _oscap_pcre_opts_to_pcre(options), &errno, &erroffset2, NULL);
111110
if (res->re == NULL) {
112111
PCRE2_UCHAR8 errmsg[PCRE2_ERR_BUF_SIZE];
@@ -139,13 +138,9 @@ int oscap_pcre_exec(const oscap_pcre_t *opcre, const char *subject,
139138
// The ovecsize is multiplied by 3 in the code for compatibility with PCRE1
140139
int ovecsize2 = ovecsize/3;
141140
pcre2_match_data_8 *mdata = pcre2_match_data_create_8(ovecsize2, NULL);
142-
dD("pcre2_match_8: subj=%s", subject);
143141
rc = pcre2_match_8(opcre->re, (PCRE2_SPTR8)subject, length, startoffset, _oscap_pcre_opts_to_pcre(options), mdata, opcre->re_ctx);
144-
dD("pcre2_match_8: rc=%d, ", rc);
145142
if (rc > PCRE2_ERROR_NOMATCH) {
146143
PCRE2_SIZE *ovecp = pcre2_get_ovector_pointer_8(mdata);
147-
uint32_t ovecp_count = pcre2_get_ovector_count_8(mdata);
148-
dD("pcre2_match_8: pcre2_get_ovector_count_8=%d", ovecp_count);
149144
for (int i = 0; i < rc; i++) {
150145
if (i < ovecsize2) {
151146
ovector[i*2] = ovecp[i*2];

0 commit comments

Comments
 (0)