preserve errno for free calls

This is a future POSIX requirement recently implemented by musl and
glibc.
pull/211/head TQ2B.230505.005.A1.2023060700
Daniel Micay 2023-02-17 12:56:26 -05:00
parent 2e9daf3122
commit d3152b8e8f
1 changed files with 6 additions and 0 deletions

View File

@ -658,6 +658,7 @@ static void enqueue_free_slab(struct size_class *c, struct slab_metadata *metada
c->free_slabs_tail = substitute; c->free_slabs_tail = substitute;
} }
// preserves errno
static inline void deallocate_small(void *p, const size_t *expected_size) { static inline void deallocate_small(void *p, const size_t *expected_size) {
struct slab_size_class_info size_class_info = slab_size_class(p); struct slab_size_class_info size_class_info = slab_size_class(p);
size_t class = size_class_info.class; size_t class = size_class_info.class;
@ -770,6 +771,7 @@ static inline void deallocate_small(void *p, const size_t *expected_size) {
metadata->prev = NULL; metadata->prev = NULL;
if (c->empty_slabs_total + slab_size > max_empty_slabs_total) { if (c->empty_slabs_total + slab_size > max_empty_slabs_total) {
int saved_errno = errno;
if (!memory_map_fixed(slab, slab_size)) { if (!memory_map_fixed(slab, slab_size)) {
label_slab(slab, slab_size, class); label_slab(slab, slab_size, class);
stats_slab_deallocate(c, slab_size); stats_slab_deallocate(c, slab_size);
@ -778,6 +780,7 @@ static inline void deallocate_small(void *p, const size_t *expected_size) {
return; return;
} }
memory_purge(slab, slab_size); memory_purge(slab, slab_size);
errno = saved_errno;
// handle out-of-memory by putting it into the empty slabs list // handle out-of-memory by putting it into the empty slabs list
} }
@ -1534,6 +1537,7 @@ EXPORT void *h_pvalloc(size_t size) {
} }
#endif #endif
// preserves errno
EXPORT void h_free(void *p) { EXPORT void h_free(void *p) {
if (p == NULL) { if (p == NULL) {
return; return;
@ -1546,7 +1550,9 @@ EXPORT void h_free(void *p) {
return; return;
} }
int saved_errno = errno;
deallocate_large(p, NULL); deallocate_large(p, NULL);
errno = saved_errno;
thread_seal_metadata(); thread_seal_metadata();
} }