Skip to content

Commit bbf22f8

Browse files
author
Edward Thomson
committed
clar: Introduce assertion helpers for threads
Don't `cl_git_pass` in a child thread. When the assertion fails, clar will `longjmp` to its error handler, but: > The effect of a call to longjmp() where initialization of the jmp_buf > structure was not performed in the calling thread is undefined. Instead, set up an error context that threads can populate, and the caller can check.
1 parent 9947906 commit bbf22f8

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

tests/clar_libgit2.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,47 @@
4141
} \
4242
} while(0)
4343

44+
/**
45+
* Thread safe assertions; you cannot use `cl_git_report_failure` from a
46+
* child thread since it will try to `longjmp` to abort and "the effect of
47+
* a call to longjmp() where initialization of the jmp_buf structure was
48+
* not performed in the calling thread is undefined."
49+
*
50+
* Instead, callers can provide a clar thread error context to a thread,
51+
* which will populate and return it on failure. Callers can check the
52+
* status with `cl_git_thread_check`.
53+
*/
54+
typedef struct {
55+
int error;
56+
const char *file;
57+
int line;
58+
const char *expr;
59+
char error_msg[4096];
60+
} cl_git_thread_err;
61+
62+
#define cl_git_thread_pass(threaderr, expr) cl_git_thread_pass_(threaderr, (expr), __FILE__, __LINE__)
63+
64+
#define cl_git_thread_pass_(__threaderr, __expr, __file, __line) do { \
65+
giterr_clear(); \
66+
if ((((cl_git_thread_err *)__threaderr)->error = (__expr)) != 0) { \
67+
const git_error *_last = giterr_last(); \
68+
((cl_git_thread_err *)__threaderr)->file = __file; \
69+
((cl_git_thread_err *)__threaderr)->line = __line; \
70+
((cl_git_thread_err *)__threaderr)->expr = "Function call failed: " #__expr; \
71+
p_snprintf(((cl_git_thread_err *)__threaderr)->error_msg, 4096, "thread 0x%" PRIxZ " - error %d - %s", \
72+
git_thread_currentid(), ((cl_git_thread_err *)__threaderr)->error, \
73+
_last ? _last->message : "<no message>"); \
74+
git_thread_exit(__threaderr); \
75+
} \
76+
} while (0)
77+
78+
static void cl_git_thread_check(void *data)
79+
{
80+
cl_git_thread_err *threaderr = (cl_git_thread_err *)data;
81+
if (threaderr->error != 0)
82+
clar__assert(0, threaderr->file, threaderr->line, threaderr->expr, threaderr->error_msg, 1);
83+
}
84+
4485
void cl_git_report_failure(int, const char *, int, const char *);
4586

4687
#define cl_assert_at_line(expr,file,line) \

0 commit comments

Comments
 (0)