aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorTheo Buehler <tb@openbsd.org>2023-12-12 23:20:44 +0100
committerTheo Buehler <tb@openbsd.org>2023-12-12 23:25:06 +0100
commit0491aef86c41e9d1de19a64e1780ff82d35ccf54 (patch)
tree995f6c473e1807bbc14eabe0c1fa0399b4300327 /include
parent223bc4e01e283db48693f631852a0f83ea232308 (diff)
downloadportable-0491aef86c41e9d1de19a64e1780ff82d35ccf54.tar.gz
portable-0491aef86c41e9d1de19a64e1780ff82d35ccf54.tar.bz2
portable-0491aef86c41e9d1de19a64e1780ff82d35ccf54.zip
pthreads.h: avoid undefined behavior
You can't pass a function pointer through a void pointer. So wrap the pthread callback in a struct. Fixes #966
Diffstat (limited to 'include')
-rw-r--r--include/compat/pthread.h11
1 files changed, 8 insertions, 3 deletions
diff --git a/include/compat/pthread.h b/include/compat/pthread.h
index 1ab011c..ed1b9dc 100644
--- a/include/compat/pthread.h
+++ b/include/compat/pthread.h
@@ -30,18 +30,23 @@ struct pthread_once {
30}; 30};
31typedef struct pthread_once pthread_once_t; 31typedef struct pthread_once pthread_once_t;
32 32
33struct _pthread_win32_cb_arg {
34 void (*cb)(void);
35};
36
33static inline BOOL CALLBACK 37static inline BOOL CALLBACK
34_pthread_once_win32_cb(PINIT_ONCE once, PVOID param, PVOID *context) 38_pthread_once_win32_cb(PINIT_ONCE once, PVOID param, PVOID *context)
35{ 39{
36 void (*cb) (void) = param; 40 struct _pthread_win32_cb_arg *arg = param;
37 cb(); 41 arg->cb();
38 return TRUE; 42 return TRUE;
39} 43}
40 44
41static inline int 45static inline int
42pthread_once(pthread_once_t *once, void (*cb) (void)) 46pthread_once(pthread_once_t *once, void (*cb) (void))
43{ 47{
44 BOOL rc = InitOnceExecuteOnce(&once->once, _pthread_once_win32_cb, cb, NULL); 48 struct _pthread_win32_cb_arg arg = { .cb = cb };
49 BOOL rc = InitOnceExecuteOnce(&once->once, _pthread_once_win32_cb, &arg, NULL);
45 if (rc == 0) 50 if (rc == 0)
46 return -1; 51 return -1;
47 else 52 else