Skip to content

Commit 56b3621

Browse files
jeromekelleherbenjeffery
authored andcommitted
Add TSK_TRACE_ERRORS to optionally print errors in the C code
1 parent 0e2fcc5 commit 56b3621

11 files changed

+538
-488
lines changed

c/CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
[1.1.4] - 2024-XX-XX
33
--------------------
44

5+
**Changes**
56

7+
- Added the TSK_TRACE_ERRORS macro to enable tracing of errors in the C library.
8+
This is useful for debugging as errors will print to stderr when set.
9+
(:user:`jeromekelleher`, :pr:`3095`).
610

711
--------------------
812
[1.1.3] - 2024-10-16

c/meson.build

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ project('tskit', ['c', 'cpp'],
33
default_options: ['c_std=c99', 'cpp_std=c++11']
44
)
55

6+
debug_c_args = []
7+
if get_option('buildtype').startswith('debug')
8+
debug_c_args = ['-DTSK_TRACE_ERRORS']
9+
endif
10+
611
kastore_proj = subproject('kastore')
712
kastore_dep = kastore_proj.get_variable('kastore_dep')
813
kastore_inc = kastore_proj.get_variable('kastore_inc')
@@ -16,7 +21,7 @@ extra_c_args = [
1621
'-Wmissing-prototypes', '-Wstrict-prototypes',
1722
'-Wconversion', '-Wshadow', '-Wpointer-arith', '-Wcast-align',
1823
'-Wcast-qual', '-Wwrite-strings', '-Wnested-externs',
19-
'-fshort-enums', '-fno-common']
24+
'-fshort-enums', '-fno-common'] + debug_c_args
2025

2126
lib_sources = [
2227
'tskit/core.c', 'tskit/tables.c', 'tskit/trees.c',

c/tskit/convert.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* MIT License
33
*
4-
* Copyright (c) 2018-2021 Tskit Developers
4+
* Copyright (c) 2018-2025 Tskit Developers
55
* Copyright (c) 2015-2017 University of Oxford
66
*
77
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -68,11 +68,11 @@ tsk_newick_converter_run(
6868
const char *label_format = ms_labels ? "%d" : "n%d";
6969

7070
if (root < 0 || root >= (tsk_id_t) self->tree->num_nodes) {
71-
ret = TSK_ERR_NODE_OUT_OF_BOUNDS;
71+
ret = tsk_trace_error(TSK_ERR_NODE_OUT_OF_BOUNDS);
7272
goto out;
7373
}
7474
if (buffer == NULL) {
75-
ret = TSK_ERR_BAD_PARAM_VALUE;
75+
ret = tsk_trace_error(TSK_ERR_BAD_PARAM_VALUE);
7676
goto out;
7777
}
7878
root_parent = tree->parent[root];
@@ -82,7 +82,7 @@ tsk_newick_converter_run(
8282
v = stack[stack_top];
8383
if (tree->left_child[v] != TSK_NULL && v != u) {
8484
if (s >= buffer_size) {
85-
ret = TSK_ERR_BUFFER_OVERFLOW;
85+
ret = tsk_trace_error(TSK_ERR_BUFFER_OVERFLOW);
8686
goto out;
8787
}
8888
buffer[s] = '(';
@@ -104,17 +104,17 @@ tsk_newick_converter_run(
104104
}
105105
if (label != -1) {
106106
if (s >= buffer_size) {
107-
ret = TSK_ERR_BUFFER_OVERFLOW;
107+
ret = tsk_trace_error(TSK_ERR_BUFFER_OVERFLOW);
108108
goto out;
109109
}
110110
r = snprintf(buffer + s, buffer_size - s, label_format, label);
111111
if (r < 0) {
112-
ret = TSK_ERR_IO;
112+
ret = tsk_trace_error(TSK_ERR_IO);
113113
goto out;
114114
}
115115
s += (size_t) r;
116116
if (s >= buffer_size) {
117-
ret = TSK_ERR_BUFFER_OVERFLOW;
117+
ret = tsk_trace_error(TSK_ERR_BUFFER_OVERFLOW);
118118
goto out;
119119
}
120120
}
@@ -123,12 +123,12 @@ tsk_newick_converter_run(
123123
r = snprintf(buffer + s, buffer_size - s, ":%.*f", (int) self->precision,
124124
branch_length);
125125
if (r < 0) {
126-
ret = TSK_ERR_IO;
126+
ret = tsk_trace_error(TSK_ERR_IO);
127127
goto out;
128128
}
129129
s += (size_t) r;
130130
if (s >= buffer_size) {
131-
ret = TSK_ERR_BUFFER_OVERFLOW;
131+
ret = tsk_trace_error(TSK_ERR_BUFFER_OVERFLOW);
132132
goto out;
133133
}
134134
if (v == tree->right_child[u]) {
@@ -141,7 +141,7 @@ tsk_newick_converter_run(
141141
}
142142
}
143143
if ((s + 1) >= buffer_size) {
144-
ret = TSK_ERR_BUFFER_OVERFLOW;
144+
ret = tsk_trace_error(TSK_ERR_BUFFER_OVERFLOW);
145145
goto out;
146146
}
147147
buffer[s] = ';';
@@ -164,7 +164,7 @@ tsk_newick_converter_init(tsk_newick_converter_t *self, const tsk_tree_t *tree,
164164
self->traversal_stack
165165
= tsk_malloc(tsk_tree_get_size_bound(tree) * sizeof(*self->traversal_stack));
166166
if (self->traversal_stack == NULL) {
167-
ret = TSK_ERR_NO_MEMORY;
167+
ret = tsk_trace_error(TSK_ERR_NO_MEMORY);
168168
goto out;
169169
}
170170
out:

c/tskit/core.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* MIT License
33
*
4-
* Copyright (c) 2019-2024 Tskit Developers
4+
* Copyright (c) 2019-2025 Tskit Developers
55
* Copyright (c) 2015-2018 University of Oxford
66
*
77
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -43,22 +43,24 @@ static int TSK_WARN_UNUSED
4343
get_random_bytes(uint8_t *buf)
4444
{
4545
/* Based on CPython's code in bootstrap_hash.c */
46-
int ret = TSK_ERR_GENERATE_UUID;
46+
int ret = 0;
4747
HCRYPTPROV hCryptProv = (HCRYPTPROV) NULL;
4848

4949
if (!CryptAcquireContext(
5050
&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
51+
ret = tsk_trace_error(TSK_ERR_GENERATE_UUID);
5152
goto out;
5253
}
5354
if (!CryptGenRandom(hCryptProv, (DWORD) UUID_NUM_BYTES, buf)) {
55+
ret = tsk_trace_error(TSK_ERR_GENERATE_UUID);
5456
goto out;
5557
}
5658
if (!CryptReleaseContext(hCryptProv, 0)) {
5759
hCryptProv = (HCRYPTPROV) NULL;
60+
ret = tsk_trace_error(TSK_ERR_GENERATE_UUID);
5861
goto out;
5962
}
6063
hCryptProv = (HCRYPTPROV) NULL;
61-
ret = 0;
6264
out:
6365
if (hCryptProv != (HCRYPTPROV) NULL) {
6466
CryptReleaseContext(hCryptProv, 0);
@@ -72,19 +74,21 @@ get_random_bytes(uint8_t *buf)
7274
static int TSK_WARN_UNUSED
7375
get_random_bytes(uint8_t *buf)
7476
{
75-
int ret = TSK_ERR_GENERATE_UUID;
77+
int ret = 0;
7678
FILE *f = fopen("/dev/urandom", "r");
7779

7880
if (f == NULL) {
81+
ret = tsk_trace_error(TSK_ERR_GENERATE_UUID);
7982
goto out;
8083
}
8184
if (fread(buf, UUID_NUM_BYTES, 1, f) != 1) {
85+
ret = tsk_trace_error(TSK_ERR_GENERATE_UUID);
8286
goto out;
8387
}
8488
if (fclose(f) != 0) {
89+
ret = tsk_trace_error(TSK_ERR_GENERATE_UUID);
8590
goto out;
8691
}
87-
ret = 0;
8892
out:
8993
return ret;
9094
}
@@ -111,7 +115,7 @@ tsk_generate_uuid(char *dest, int TSK_UNUSED(flags))
111115
buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12],
112116
buf[13], buf[14], buf[15])
113117
< 0) {
114-
ret = TSK_ERR_GENERATE_UUID;
118+
ret = tsk_trace_error(TSK_ERR_GENERATE_UUID);
115119
goto out;
116120
}
117121
out:
@@ -764,7 +768,7 @@ tsk_blkalloc_init(tsk_blkalloc_t *self, size_t chunk_size)
764768

765769
tsk_memset(self, 0, sizeof(tsk_blkalloc_t));
766770
if (chunk_size < 1) {
767-
ret = TSK_ERR_BAD_PARAM_VALUE;
771+
ret = tsk_trace_error(TSK_ERR_BAD_PARAM_VALUE);
768772
goto out;
769773
}
770774
self->chunk_size = chunk_size;
@@ -775,12 +779,12 @@ tsk_blkalloc_init(tsk_blkalloc_t *self, size_t chunk_size)
775779
self->num_chunks = 0;
776780
self->mem_chunks = malloc(sizeof(char *));
777781
if (self->mem_chunks == NULL) {
778-
ret = TSK_ERR_NO_MEMORY;
782+
ret = tsk_trace_error(TSK_ERR_NO_MEMORY);
779783
goto out;
780784
}
781785
self->mem_chunks[0] = malloc(chunk_size);
782786
if (self->mem_chunks[0] == NULL) {
783-
ret = TSK_ERR_NO_MEMORY;
787+
ret = tsk_trace_error(TSK_ERR_NO_MEMORY);
784788
goto out;
785789
}
786790
self->num_chunks = 1;
@@ -1256,7 +1260,7 @@ tsk_bit_array_init(tsk_bit_array_t *self, tsk_size_t num_bits, tsk_size_t length
12561260
+ (num_bits % TSK_BIT_ARRAY_NUM_BITS ? 1 : 0);
12571261
self->data = tsk_calloc(self->size * length, sizeof(*self->data));
12581262
if (self->data == NULL) {
1259-
ret = TSK_ERR_NO_MEMORY;
1263+
ret = tsk_trace_error(TSK_ERR_NO_MEMORY);
12601264
goto out;
12611265
}
12621266
out:

c/tskit/core.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* MIT License
33
*
4-
* Copyright (c) 2019-2024 Tskit Developers
4+
* Copyright (c) 2019-2025 Tskit Developers
55
* Copyright (c) 2015-2018 University of Oxford
66
*
77
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -953,6 +953,21 @@ not be freed by client code.
953953
*/
954954
const char *tsk_strerror(int err);
955955

956+
#ifdef TSK_TRACE_ERRORS
957+
958+
static inline int
959+
_tsk_trace_error(int err, int line, const char *file)
960+
{
961+
fprintf(stderr, "tskit-trace-error: %d='%s' at line %d in %s\n", err,
962+
tsk_strerror(err), line, file);
963+
return err;
964+
}
965+
966+
#define tsk_trace_error(err) (_tsk_trace_error(err, __LINE__, __FILE__))
967+
#else
968+
#define tsk_trace_error(err) (err)
969+
#endif
970+
956971
#ifndef TSK_BUG_ASSERT_MESSAGE
957972
#define TSK_BUG_ASSERT_MESSAGE \
958973
"If you are using tskit directly please open an issue on" \

0 commit comments

Comments
 (0)