aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhilipp Stephani2018-06-02 22:35:22 +0200
committerPhilipp Stephani2018-06-09 18:47:10 +0200
commitb4dcac2d6ae376788dca11b88b874a9ecaf986df (patch)
treee6185efc4660b5192f5c6c78017768e18ac9440b /src
parentca369a8ca67a4cb279a5412cca36109e719a520e (diff)
downloademacs-b4dcac2d6ae376788dca11b88b874a9ecaf986df.tar.gz
emacs-b4dcac2d6ae376788dca11b88b874a9ecaf986df.zip
Make error checking for thread functions stricter.
* src/systhread.c (sys_thread_create): Change return type to bool. Check for errors returned by pthread_attr_setstacksize and pthread_attr_destroy. (sys_mutex_init): Abort on errors. Enable mutex checks when checking is enabled. (sys_cond_init): Abort on errors. (sys_mutex_lock, sys_mutex_unlock, sys_cond_wait) (sys_cond_signal, sys_cond_broadcast, sys_cond_destroy): Check for errors in debug mode.
Diffstat (limited to 'src')
-rw-r--r--src/systhread.c78
-rw-r--r--src/systhread.h24
2 files changed, 79 insertions, 23 deletions
diff --git a/src/systhread.c b/src/systhread.c
index e972ed398ac..d53b5c207b6 100644
--- a/src/systhread.c
+++ b/src/systhread.c
@@ -18,6 +18,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
18 18
19#include <config.h> 19#include <config.h>
20#include <setjmp.h> 20#include <setjmp.h>
21#include <stdio.h>
22#include <string.h>
21#include "lisp.h" 23#include "lisp.h"
22 24
23#ifdef HAVE_NS 25#ifdef HAVE_NS
@@ -80,11 +82,11 @@ sys_thread_equal (sys_thread_t t, sys_thread_t u)
80 return t == u; 82 return t == u;
81} 83}
82 84
83int 85bool
84sys_thread_create (sys_thread_t *t, const char *name, 86sys_thread_create (sys_thread_t *t, const char *name,
85 thread_creation_function *func, void *datum) 87 thread_creation_function *func, void *datum)
86{ 88{
87 return 0; 89 return false;
88} 90}
89 91
90void 92void
@@ -103,43 +105,77 @@ sys_thread_yield (void)
103void 105void
104sys_mutex_init (sys_mutex_t *mutex) 106sys_mutex_init (sys_mutex_t *mutex)
105{ 107{
106 pthread_mutex_init (mutex, NULL); 108 pthread_mutexattr_t *attr_ptr;
109#ifdef ENABLE_CHECKING
110 pthread_mutexattr_t attr;
111 {
112 int error = pthread_mutexattr_init (&attr);
113 eassert (error == 0);
114 error = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK);
115 eassert (error == 0);
116 }
117 attr_ptr = &attr;
118#else
119 attr_ptr = NULL;
120#endif
121 int error = pthread_mutex_init (mutex, attr_ptr);
122 /* We could get ENOMEM. Can't do anything except aborting. */
123 if (error != 0)
124 {
125 fprintf (stderr, "\npthread_mutex_init failed: %s\n", strerror (error));
126 emacs_abort ();
127 }
128#ifdef ENABLE_CHECKING
129 error = pthread_mutexattr_destroy (&attr);
130 eassert (error == 0);
131#endif
107} 132}
108 133
109void 134void
110sys_mutex_lock (sys_mutex_t *mutex) 135sys_mutex_lock (sys_mutex_t *mutex)
111{ 136{
112 pthread_mutex_lock (mutex); 137 int error = pthread_mutex_lock (mutex);
138 eassert (error == 0);
113} 139}
114 140
115void 141void
116sys_mutex_unlock (sys_mutex_t *mutex) 142sys_mutex_unlock (sys_mutex_t *mutex)
117{ 143{
118 pthread_mutex_unlock (mutex); 144 int error = pthread_mutex_unlock (mutex);
145 eassert (error == 0);
119} 146}
120 147
121void 148void
122sys_cond_init (sys_cond_t *cond) 149sys_cond_init (sys_cond_t *cond)
123{ 150{
124 pthread_cond_init (cond, NULL); 151 int error = pthread_cond_init (cond, NULL);
152 /* We could get ENOMEM. Can't do anything except aborting. */
153 if (error != 0)
154 {
155 fprintf (stderr, "\npthread_cond_init failed: %s\n", strerror (error));
156 emacs_abort ();
157 }
125} 158}
126 159
127void 160void
128sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex) 161sys_cond_wait (sys_cond_t *cond, sys_mutex_t *mutex)
129{ 162{
130 pthread_cond_wait (cond, mutex); 163 int error = pthread_cond_wait (cond, mutex);
164 eassert (error == 0);
131} 165}
132 166
133void 167void
134sys_cond_signal (sys_cond_t *cond) 168sys_cond_signal (sys_cond_t *cond)
135{ 169{
136 pthread_cond_signal (cond); 170 int error = pthread_cond_signal (cond);
171 eassert (error == 0);
137} 172}
138 173
139void 174void
140sys_cond_broadcast (sys_cond_t *cond) 175sys_cond_broadcast (sys_cond_t *cond)
141{ 176{
142 pthread_cond_broadcast (cond); 177 int error = pthread_cond_broadcast (cond);
178 eassert (error == 0);
143#ifdef HAVE_NS 179#ifdef HAVE_NS
144 /* Send an app defined event to break out of the NS run loop. 180 /* Send an app defined event to break out of the NS run loop.
145 It seems that if ns_select is running the NS run loop, this 181 It seems that if ns_select is running the NS run loop, this
@@ -152,7 +188,8 @@ sys_cond_broadcast (sys_cond_t *cond)
152void 188void
153sys_cond_destroy (sys_cond_t *cond) 189sys_cond_destroy (sys_cond_t *cond)
154{ 190{
155 pthread_cond_destroy (cond); 191 int error = pthread_cond_destroy (cond);
192 eassert (error == 0);
156} 193}
157 194
158sys_thread_t 195sys_thread_t
@@ -167,22 +204,25 @@ sys_thread_equal (sys_thread_t t, sys_thread_t u)
167 return pthread_equal (t, u); 204 return pthread_equal (t, u);
168} 205}
169 206
170int 207bool
171sys_thread_create (sys_thread_t *thread_ptr, const char *name, 208sys_thread_create (sys_thread_t *thread_ptr, const char *name,
172 thread_creation_function *func, void *arg) 209 thread_creation_function *func, void *arg)
173{ 210{
174 pthread_attr_t attr; 211 pthread_attr_t attr;
175 int result = 0; 212 bool result = false;
176 213
177 if (pthread_attr_init (&attr)) 214 if (pthread_attr_init (&attr))
178 return 0; 215 return false;
179 216
180 /* Avoid crash on macOS with deeply nested GC (Bug#30364). */ 217 /* Avoid crash on macOS with deeply nested GC (Bug#30364). */
181 size_t stack_size; 218 size_t stack_size;
182 size_t required_stack_size = sizeof (void *) * 1024 * 1024; 219 size_t required_stack_size = sizeof (void *) * 1024 * 1024;
183 if (pthread_attr_getstacksize (&attr, &stack_size) == 0 220 if (pthread_attr_getstacksize (&attr, &stack_size) == 0
184 && stack_size < required_stack_size) 221 && stack_size < required_stack_size)
185 pthread_attr_setstacksize (&attr, required_stack_size); 222 {
223 if (pthread_attr_setstacksize (&attr, required_stack_size) != 0)
224 goto out;
225 }
186 226
187 if (!pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED)) 227 if (!pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))
188 { 228 {
@@ -193,7 +233,9 @@ sys_thread_create (sys_thread_t *thread_ptr, const char *name,
193#endif 233#endif
194 } 234 }
195 235
196 pthread_attr_destroy (&attr); 236 out: ;
237 int error = pthread_attr_destroy (&attr);
238 eassert (error == 0);
197 239
198 return result; 240 return result;
199} 241}
@@ -359,7 +401,7 @@ w32_beginthread_wrapper (void *arg)
359 (void)thread_start_address (arg); 401 (void)thread_start_address (arg);
360} 402}
361 403
362int 404bool
363sys_thread_create (sys_thread_t *thread_ptr, const char *name, 405sys_thread_create (sys_thread_t *thread_ptr, const char *name,
364 thread_creation_function *func, void *arg) 406 thread_creation_function *func, void *arg)
365{ 407{
@@ -383,7 +425,7 @@ sys_thread_create (sys_thread_t *thread_ptr, const char *name,
383 rule in many places... */ 425 rule in many places... */
384 thandle = _beginthread (w32_beginthread_wrapper, stack_size, arg); 426 thandle = _beginthread (w32_beginthread_wrapper, stack_size, arg);
385 if (thandle == (uintptr_t)-1L) 427 if (thandle == (uintptr_t)-1L)
386 return 0; 428 return false;
387 429
388 /* Kludge alert! We use the Windows thread ID, an unsigned 32-bit 430 /* Kludge alert! We use the Windows thread ID, an unsigned 32-bit
389 number, as the sys_thread_t type, because that ID is the only 431 number, as the sys_thread_t type, because that ID is the only
@@ -398,7 +440,7 @@ sys_thread_create (sys_thread_t *thread_ptr, const char *name,
398 Therefore, we return some more or less arbitrary value of the 440 Therefore, we return some more or less arbitrary value of the
399 thread ID from this function. */ 441 thread ID from this function. */
400 *thread_ptr = thandle & 0xFFFFFFFF; 442 *thread_ptr = thandle & 0xFFFFFFFF;
401 return 1; 443 return true;
402} 444}
403 445
404void 446void
diff --git a/src/systhread.h b/src/systhread.h
index 5dbb12dffb6..3805cb261f1 100644
--- a/src/systhread.h
+++ b/src/systhread.h
@@ -19,6 +19,18 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19#ifndef SYSTHREAD_H 19#ifndef SYSTHREAD_H
20#define SYSTHREAD_H 20#define SYSTHREAD_H
21 21
22#include <stdbool.h>
23
24#ifndef __has_attribute
25# define __has_attribute(a) false
26#endif
27
28#if __has_attribute (__warn_unused_result__)
29# define ATTRIBUTE_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
30#else
31# define ATTRIBUTE_WARN_UNUSED_RESULT
32#endif
33
22#ifdef THREADS_ENABLED 34#ifdef THREADS_ENABLED
23 35
24#ifdef HAVE_PTHREAD 36#ifdef HAVE_PTHREAD
@@ -99,12 +111,14 @@ extern void sys_cond_signal (sys_cond_t *);
99extern void sys_cond_broadcast (sys_cond_t *); 111extern void sys_cond_broadcast (sys_cond_t *);
100extern void sys_cond_destroy (sys_cond_t *); 112extern void sys_cond_destroy (sys_cond_t *);
101 113
102extern sys_thread_t sys_thread_self (void); 114extern sys_thread_t sys_thread_self (void)
103extern bool sys_thread_equal (sys_thread_t, sys_thread_t); 115 ATTRIBUTE_WARN_UNUSED_RESULT;
116extern bool sys_thread_equal (sys_thread_t, sys_thread_t)
117 ATTRIBUTE_WARN_UNUSED_RESULT;
104 118
105extern int sys_thread_create (sys_thread_t *, const char *, 119extern bool sys_thread_create (sys_thread_t *, const char *,
106 thread_creation_function *, 120 thread_creation_function *, void *)
107 void *); 121 ATTRIBUTE_WARN_UNUSED_RESULT;
108 122
109extern void sys_thread_yield (void); 123extern void sys_thread_yield (void);
110 124