Skip to content

Commit 78daf3a

Browse files
nocanstillbbclaude
authored andcommitted
fix: release mode hang and enable Ubuntu CI unit tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ff149e0 commit 78daf3a

4 files changed

Lines changed: 46 additions & 24 deletions

File tree

.github/workflows/cmake-multi-platform.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ jobs:
4848
cmake -B ${{ steps.strings.outputs.build-output-dir }}
4949
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
5050
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
51+
-DUNIT_TEST=ON
5152
-S ${{ github.workspace }}
5253
5354
- name: Build

src/consumer.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <assert.h>
22
#include <pthread.h>
33
#include <stdatomic.h>
4+
#include <stdio.h>
45
#include <stdlib.h>
56
#include <unistd.h>
67

@@ -16,7 +17,8 @@
1617

1718
static void enque_event_exit(struct log_consumer *logc)
1819
{
19-
assert(!pthread_mutex_lock(&logc->event.queue_in_lock));
20+
int _r = pthread_mutex_lock(&logc->event.queue_in_lock);
21+
assert(_r == 0); (void)_r;
2022
logc->exit = true; /* ensure this is the last */
2123
for (;;) {
2224
struct msg_head *head = fifo_reserve(logc->event.queue, msg_cmd_size());
@@ -31,15 +33,19 @@ static void enque_event_exit(struct log_consumer *logc)
3133
fifo_commit(logc->event.queue, head);
3234
break;
3335
}
34-
assert(!pthread_mutex_unlock(&logc->event.queue_in_lock));
36+
_r = pthread_mutex_unlock(&logc->event.queue_in_lock);
37+
assert(_r == 0); (void)_r;
3538
}
3639

3740
static void enque_signal(struct log_consumer *logc)
3841
{
39-
assert(!pthread_mutex_lock(&logc->event.siglock));
42+
int _r = pthread_mutex_lock(&logc->event.siglock);
43+
assert(_r == 0); (void)_r;
4044
logc->event.sig_send++;
41-
assert(!pthread_cond_signal(&logc->event.cond));
42-
assert(!pthread_mutex_unlock(&logc->event.siglock));
45+
_r = pthread_cond_signal(&logc->event.cond);
46+
assert(_r == 0); (void)_r;
47+
_r = pthread_mutex_unlock(&logc->event.siglock);
48+
assert(_r == 0); (void)_r;
4349
}
4450

4551
static void handle_log(struct log_consumer *logc, struct msg_head *head, bool *exit)
@@ -66,10 +72,13 @@ static void handle_log(struct log_consumer *logc, struct msg_head *head, bool *e
6672
*exit = true;
6773
return;
6874
} else if (cmd->cmd == MSG_CMD_FLUSH) {
69-
assert(!pthread_mutex_lock(&logc->flush.siglock));
75+
int _r = pthread_mutex_lock(&logc->flush.siglock);
76+
assert(_r == 0); (void)_r;
7077
logc->flush.done = true;
71-
assert(!pthread_cond_signal(&logc->flush.cond));
72-
assert(!pthread_mutex_unlock(&logc->flush.siglock));
78+
_r = pthread_cond_signal(&logc->flush.cond);
79+
assert(_r == 0); (void)_r;
80+
_r = pthread_mutex_unlock(&logc->flush.siglock);
81+
assert(_r == 0); (void)_r;
7382
}
7483
offset += msg_cmd_size();
7584
break;
@@ -119,24 +128,29 @@ static void *logc_func(void *arg)
119128
pthread_mutex_unlock(&logc->event.siglock);
120129
/* has data */
121130

122-
for (struct msg_head *head = fifo_peek(logc->event.queue); head;
131+
/* pending: number of committed/discarded messages still to consume
132+
* in this wakeup. sig_recv is only incremented when a message is
133+
* actually dequeued, so it never overshoots sig_send. */
134+
unsigned int pending = sig_send_cache - logc->event.sig_recv;
135+
unsigned long reserved_spins = 0;
136+
for (struct msg_head *head = fifo_peek(logc->event.queue);
137+
head && pending > 0;
123138
head = fifo_peek(logc->event.queue)) {
124-
logc->event.sig_recv++;
125-
126139
unsigned flag = atomic_load_explicit(&head->flags, memory_order_acquire);
127140
if (flag == MSG_HEAD_FLAG_RESERVED) {
128-
if (logc->event.sig_recv == sig_send_cache) {
129-
/* goto wait til fist commited */
130-
break;
131-
}
141+
/* spin-wait for the producer to finish committing */
142+
reserved_spins++;
132143
continue;
133144
}
145+
reserved_spins = 0;
134146

147+
pending--;
148+
logc->event.sig_recv++;
135149
if (flag == MSG_HEAD_FLAG_COMMITED) {
136150
handle_log(logc, head, &exit);
137151
} else if (flag == MSG_HEAD_FLAG_DISCARDED) {
138152
} else {
139-
assert(1);
153+
assert(0); /* unexpected flag value */
140154
}
141155
fifo_out(logc->event.queue, head);
142156
}
@@ -342,7 +356,8 @@ void log_consumer_queue_commit_signal(struct log_consumer *logc, struct msg_head
342356

343357
void log_consumer_queue_flush(struct log_consumer *logc)
344358
{
345-
assert(!pthread_mutex_lock(&logc->event.queue_in_lock));
359+
int _r = pthread_mutex_lock(&logc->event.queue_in_lock);
360+
assert(_r == 0); (void)_r;
346361
for (;;) {
347362
struct msg_head *head = fifo_reserve(logc->event.queue, msg_cmd_size());
348363
if (!head) {
@@ -357,7 +372,8 @@ void log_consumer_queue_flush(struct log_consumer *logc)
357372
fifo_commit(logc->event.queue, head);
358373
break;
359374
}
360-
assert(!pthread_mutex_unlock(&logc->event.queue_in_lock));
375+
_r = pthread_mutex_unlock(&logc->event.queue_in_lock);
376+
assert(_r == 0); (void)_r;
361377
enque_signal(logc);
362378

363379
pthread_mutex_lock(&logc->flush.siglock);

src/zlog.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,9 @@ static void _log(zlog_category_t * category,
912912
goto exit;
913913
}
914914

915-
if (zlog_category_needless_level(category, level)) goto exit;
915+
if (zlog_category_needless_level(category, level)) {
916+
goto exit;
917+
}
916918

917919
zlog_fetch_thread(a_thread, exit);
918920

test/test_dzlog_conf.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ static int test(struct conf *conf)
129129
printf("init failed\n");
130130
return -1;
131131
}
132-
assert(!zlog_set_record("myoutput", output));
132+
if (zlog_set_record("myoutput", output)) { fprintf(stderr, "zlog_set_record failed\n"); return -1; }
133133
} else {
134134
ret = dzlog_init(conf->filename, "default");
135135
if (ret) {
@@ -143,20 +143,23 @@ static int test(struct conf *conf)
143143
thread_func(conf);
144144
} else {
145145
tids = malloc(conf->threadn * sizeof(*tids));
146-
assert(tids);
146+
if (!tids) { perror("malloc"); return -1; }
147147
for (int i = 0; i < conf->threadn; i++) {
148-
assert(!pthread_create(&(tids[i]), NULL, thread_func, conf));
148+
int r = pthread_create(&(tids[i]), NULL, thread_func, conf);
149+
if (r) { fprintf(stderr, "pthread_create: %d\n", r); return -1; }
149150
}
150151
}
151152

152153
for (int i = 0; i < conf->reload_cnt && conf->reload_file_num; i++) {
153-
assert(!zlog_reload(conf->reload_files[i % conf->reload_file_num]));
154+
int r = zlog_reload(conf->reload_files[i % conf->reload_file_num]);
155+
if (r) { fprintf(stderr, "zlog_reload failed\n"); return -1; }
154156
usleep(conf->reload_ms * 1000);
155157
}
156158

157159
if (conf->threadn) {
158160
for (int i = 0; i < conf->threadn; i++) {
159-
assert(!pthread_join(tids[i], NULL));
161+
int r = pthread_join(tids[i], NULL);
162+
if (r) { fprintf(stderr, "pthread_join: %d\n", r); return -1; }
160163
}
161164
free(tids);
162165
}

0 commit comments

Comments
 (0)