mhd_threads.h (20558B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2016-2025 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file src/mhd2/mhd_threads.h 41 * @brief Header for platform-independent threads abstraction 42 * @author Karlson2k (Evgeny Grin) 43 * 44 * Provides basic abstraction for threads. 45 * Any functions can be implemented as macro on some platforms 46 * unless explicitly marked otherwise. 47 * Any function argument can be skipped in macro, so avoid 48 * variable modification in function parameters. 49 * 50 * @warning Unlike pthread functions, most of functions return 51 * nonzero on success. 52 */ 53 54 #ifndef MHD_THREADS_H 55 #define MHD_THREADS_H 1 56 57 #include "mhd_sys_options.h" 58 59 #ifndef MHD_SUPPORT_THREADS 60 # error Threads support disabled by configure. 61 #endif 62 63 #if defined(mhd_THREADS_KIND_POSIX) 64 # include <pthread.h> 65 # ifndef MHD_SUPPORT_THREADS 66 # define MHD_SUPPORT_THREADS 1 67 # endif 68 #elif defined(mhd_THREADS_KIND_W32) 69 # include <windows.h> 70 # ifndef MHD_SUPPORT_THREADS 71 # define MHD_SUPPORT_THREADS 1 72 # endif 73 #else 74 # error No threading API is available. 75 #endif 76 77 #include "sys_bool_type.h" 78 #include "sys_base_types.h" 79 #include "sys_thread_entry_type.h" 80 81 #if defined(mhd_THREADS_KIND_POSIX) && defined(mhd_THREADS_KIND_W32) 82 # error Both mhd_THREADS_KIND_POSIX and mhd_THREADS_KIND_W32 are defined 83 #endif /* mhd_THREADS_KIND_POSIX && mhd_THREADS_KIND_W32 */ 84 85 #ifndef MHD_NO_THREAD_NAMES 86 # if defined(mhd_THREADS_KIND_POSIX) 87 # if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \ 88 defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) || \ 89 defined(HAVE_PTHREAD_SETNAME_NP_DARWIN) || \ 90 defined(HAVE_PTHREAD_SETNAME_NP_NETBSD) || \ 91 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \ 92 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI) 93 # define mhd_USE_THREAD_NAME 94 # endif /* HAVE_PTHREAD_SETNAME_NP */ 95 # elif defined(mhd_THREADS_KIND_W32) 96 # ifdef _MSC_FULL_VER 97 /* Thread names only available with VC compiler */ 98 # define mhd_USE_THREAD_NAME 99 # endif /* _MSC_FULL_VER */ 100 # endif 101 #endif 102 103 /* ** Thread handle - used to control the thread ** */ 104 105 #if defined(mhd_THREADS_KIND_POSIX) 106 /** 107 * The native type to control the thread from other threads 108 */ 109 typedef pthread_t mhd_thread_handle_native; 110 #elif defined(mhd_THREADS_KIND_W32) 111 /** 112 * The native type to control the thread from other threads 113 */ 114 typedef HANDLE mhd_thread_handle_native; 115 #endif 116 117 #if defined(mhd_THREADS_KIND_POSIX) 118 # if defined(__gnu_linux__) || \ 119 (defined(__linux__) && defined(__GLIBC__)) 120 /* The next part of code is disabled because it relies on undocumented 121 behaviour (while the thread ID cannot be zero with GNU C Library, it is 122 not specified anywhere officially). 123 It could be enabled for neglectable performance and size improvements. */ 124 # if 0 /* Disabled code */ 125 /** 126 * The native invalid value for native thread handle 127 */ 128 # define mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID \ 129 ((mhd_thread_handle_native) 0) 130 # endif /* Disabled code */ 131 # endif /* __gnu_linux__ || (__linux__ && __GLIBC__) */ 132 #elif defined(mhd_THREADS_KIND_W32) 133 /* On W32 the invalid value for thread handle is described directly in 134 the official documentation. */ 135 /** 136 * The native invalid value for native thread handle 137 */ 138 # define mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID \ 139 ((mhd_thread_handle_native) NULL) 140 #endif /* mhd_THREADS_KIND_W32 */ 141 142 #if defined(mhd_THREADS_KIND_POSIX) 143 /** 144 * Wait until specified thread is ended and free the thread handle on success. 145 * @param native_handle the handle to watch 146 * @return nonzero on success, zero otherwise 147 */ 148 # define mhd_join_thread(native_handle) \ 149 (! pthread_join ((native_handle), NULL)) 150 #elif defined(mhd_THREADS_KIND_W32) 151 /** 152 * Wait until specified thread is ended and the free thread handle on success. 153 * @param native_handle the handle to watch 154 * @return nonzero on success, zero otherwise 155 */ 156 # define mhd_join_thread(native_handle) \ 157 ( (WAIT_OBJECT_0 == WaitForSingleObject ( (native_handle), INFINITE)) ? \ 158 (CloseHandle ( (native_handle)), ! 0) : 0) 159 #endif 160 161 #if ! defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID) 162 /** 163 * Structure with thread handle and validity flag 164 */ 165 struct mhd_thread_handle_struct 166 { 167 bool valid; /**< true if native handle is set */ 168 mhd_thread_handle_native native; /**< the native thread handle */ 169 }; 170 /** 171 * Type with thread handle that can be set to invalid value 172 */ 173 typedef struct mhd_thread_handle_struct mhd_thread_handle; 174 175 /** 176 * Set variable pointed by @a handle_ptr to invalid (unset) value 177 */ 178 # define mhd_thread_handle_set_invalid(handle_ptr) \ 179 ((handle_ptr)->valid = false) 180 /** 181 * Set the native handle in the variable pointed by the @a handle_ptr 182 * to the @a native_val value 183 */ 184 # define mhd_thread_handle_set_native(handle_ptr,native_val) \ 185 ((handle_ptr)->valid = true, (handle_ptr)->native = native_val) 186 /** 187 * Check whether the native handle value is set in the @a handle_var variable 188 */ 189 # define mhd_thread_handle_is_valid(handle_var) \ 190 ((handle_var).valid) 191 /** 192 * Get the native handle value from the @a handle_var variable 193 */ 194 # define mhd_thread_handle_get_native(handle_var) \ 195 ((handle_var).native) 196 #else /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */ 197 /** 198 * Type with thread handle that can be set to invalid value 199 */ 200 typedef mhd_thread_handle_native mhd_thread_handle; 201 202 /** 203 * Set the variable pointed by the @a handle_ptr to the invalid (unset) value 204 */ 205 # define mhd_thread_handle_set_invalid(handle_ptr) \ 206 ((*(handle_ptr)) = mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID) 207 /** 208 * Set the native handle in the variable pointed by the @a handle_ptr 209 * to the @a native_val value 210 */ 211 # define mhd_thread_handle_set_native(handle_ptr,native_val) \ 212 ((*(handle_ptr)) = (native_val)) 213 /** 214 * Check whether the native handle value is set in the @a handle_var variable 215 */ 216 # define mhd_thread_handle_is_valid(handle_var) \ 217 (mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID != (handle_var)) 218 /** 219 * Get the native handle value from the @a handle_var variable 220 */ 221 # define mhd_thread_handle_get_native(handle_var) \ 222 (handle_var) 223 /** 224 * Get the pointer to the native handle stored the variable pointed by 225 * the @a handle_ptr pointer 226 * @note This macro could be not available if direct manipulation of 227 * the native handle is not possible 228 */ 229 # define mhd_thread_handle_get_native_ptr(handle_ptr) \ 230 (handle_ptr) 231 #endif /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */ 232 233 234 /* ** Thread ID - used to check threads match ** */ 235 236 #if defined(mhd_THREADS_KIND_POSIX) 237 /** 238 * The native type used to check whether the current thread matches 239 * the expected thread 240 */ 241 typedef pthread_t mhd_thread_ID_native; 242 243 /** 244 * Function to get the current thread native ID. 245 */ 246 # define mhd_thread_ID_native_current pthread_self 247 248 /** 249 * Check whether two native thread IDs are equal. 250 * @return non-zero if equal, zero if not equal 251 */ 252 # define mhd_thread_ID_native_equal(id1,id2) \ 253 (pthread_equal ((id1),(id2))) 254 #elif defined(mhd_THREADS_KIND_W32) 255 /** 256 * The native type used to check whether the current thread matches 257 * the expected thread 258 */ 259 typedef DWORD mhd_thread_ID_native; 260 261 /** 262 * Function to get the current thread native ID. 263 */ 264 # define mhd_thread_ID_native_current GetCurrentThreadId 265 266 /** 267 * Check whether two native thread IDs are equal. 268 * @return non-zero if equal, zero if not equal 269 */ 270 # define mhd_thread_ID_native_equal(id1,id2) \ 271 ((id1) == (id2)) 272 #endif 273 274 /** 275 * Check whether the specified thread ID matches current thread. 276 * @param id the thread ID to match 277 * @return nonzero on match, zero otherwise 278 */ 279 #define mhd_thread_ID_native_is_current_thread(id) \ 280 mhd_thread_ID_native_equal ((id), mhd_thread_ID_native_current ()) 281 282 283 #if defined(mhd_THREADS_KIND_POSIX) 284 # if defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID) 285 /** 286 * The native invalid value for native thread ID 287 */ 288 # define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \ 289 mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID 290 # endif /* mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID */ 291 #elif defined(mhd_THREADS_KIND_W32) 292 /** 293 * The native invalid value for native thread ID 294 */ 295 # define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \ 296 ((mhd_thread_ID_native) 0) 297 #endif /* mhd_THREADS_KIND_W32 */ 298 299 #if ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) 300 /** 301 * Structure with thread id and validity flag 302 */ 303 struct mhd_thread_ID_struct 304 { 305 bool valid; /**< true if native ID is set */ 306 mhd_thread_ID_native native; /**< the native thread ID */ 307 }; 308 /** 309 * Type with thread ID that can be set to the invalid value 310 */ 311 typedef struct mhd_thread_ID_struct mhd_thread_ID; 312 313 /** 314 * Set variable pointed by the @a ID_ptr to the invalid (unset) value 315 */ 316 # define mhd_thread_ID_set_invalid(ID_ptr) \ 317 ((ID_ptr)->valid = false) 318 /** 319 * Set the native ID in the variable pointed by the @a ID_ptr 320 * to the @a native_val value 321 */ 322 # define mhd_thread_ID_set_native(ID_ptr,native_val) \ 323 ((ID_ptr)->valid = true, (ID_ptr)->native = (native_val)) 324 /** 325 * Check whether the native ID value is set in the @a ID_var variable 326 */ 327 # define mhd_thread_ID_is_valid(ID_var) \ 328 ((ID_var).valid) 329 /** 330 * Get the native ID value from the @a ID_var variable 331 */ 332 # define mhd_thread_ID_get_native(ID_var) \ 333 ((ID_var).native) 334 /** 335 * Check whether the @a ID_var variable is equal current thread 336 */ 337 # define mhd_thread_ID_is_current_thread(ID_var) \ 338 (mhd_thread_ID_is_valid (ID_var) && \ 339 mhd_thread_ID_native_is_current_thread ((ID_var).native)) 340 #else /* MHD_THREAD_ID_NATIVE_INVALID_ */ 341 /** 342 * Type with thread ID that can be set to the invalid value 343 */ 344 typedef mhd_thread_ID_native mhd_thread_ID; 345 346 /** 347 * Set variable pointed by the @a ID_ptr to the invalid (unset) value 348 */ 349 # define mhd_thread_ID_set_invalid(ID_ptr) \ 350 ((*(ID_ptr)) = MHD_THREAD_ID_NATIVE_VALUE_INVALID_) 351 /** 352 * Set the native ID in the variable pointed by the @a ID_ptr 353 * to the @a native_val value 354 */ 355 # define mhd_thread_ID_set_native(ID_ptr,native_val) \ 356 ((*(ID_ptr)) = (native_val)) 357 /** 358 * Check whether the native ID value is set in the @a ID_var variable 359 */ 360 # define mhd_thread_ID_is_valid(ID_var) \ 361 (MHD_THREAD_ID_NATIVE_VALUE_INVALID_ != (ID_var)) 362 /** 363 * Get the native ID value from the @a ID_var variable 364 */ 365 # define mhd_thread_ID_get_native(ID_var) \ 366 (ID_var) 367 /** 368 * Check whether the @a ID_var variable is equal current thread 369 */ 370 # define mhd_thread_ID_is_current_thread(ID_var) \ 371 mhd_thread_ID_native_is_current_thread (ID_var) 372 #endif /* MHD_THREAD_ID_NATIVE_INVALID_ */ 373 374 /** 375 * Set current thread ID in the variable pointed by the @a ID_ptr 376 */ 377 # define mhd_thread_ID_set_current_thread(ID_ptr) \ 378 mhd_thread_ID_set_native ((ID_ptr),mhd_thread_ID_native_current ()) 379 380 381 #if defined(mhd_THREADS_KIND_POSIX) 382 # if defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID) && \ 383 ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) 384 # error \ 385 MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined 386 # elif ! defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID) && \ 387 defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) 388 # error \ 389 MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined 390 # endif 391 #endif /* mhd_THREADS_KIND_POSIX */ 392 393 /* When staring a new thread, the kernel (and thread implementation) may 394 * pause the calling (initial) thread and start the new thread. 395 * If thread identifier is assigned to variable in the initial thread then 396 * the value of the identifier variable will be undefined in the new thread 397 * until the initial thread continue processing. 398 * However, it is also possible that the new thread created, but not executed 399 * for some time while the initial thread continue execution. In this case any 400 * variable assigned in the new thread will be undefined for some time until 401 * they really processed by the new thread. 402 * To avoid data races, a special structure mhd_thread_handle_ID is used. 403 * The "handle" is assigned by calling (initial) thread and should be always 404 * defined when checked in the initial thread. 405 * The "ID" is assigned by the new thread and should be always defined when 406 * checked inside the new thread. 407 */ 408 /* Depending on implementation, pthread_create() MAY set thread ID into 409 * provided pointer and after it start thread OR start thread and after 410 * it set thread ID. In the latter case, to avoid data races, additional 411 * pthread_self() call is required in thread routine. If some platform 412 * is known for setting thread ID BEFORE starting thread macro 413 * MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined 414 * to save some resources. */ 415 416 /* #define MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 1 */ 417 418 /* * handle - must be valid when other thread knows that particular thread 419 is started. 420 * ID - must be valid when code is executed inside thread */ 421 #if defined(mhd_THREADS_KIND_POSIX) && \ 422 defined(MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD) && \ 423 defined(mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID) && \ 424 defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) && \ 425 defined(mhd_thread_handle_get_native_ptr) 426 union mhd_thread_handle_ID_ 427 { 428 mhd_thread_handle handle; /**< To be used in other threads */ 429 mhd_thread_ID ID; /**< To be used in the thread itself */ 430 }; 431 typedef union mhd_thread_handle_ID_ mhd_thread_handle_ID; 432 # define MHD_THREAD_HANDLE_ID_IS_UNION 1 433 #else /* !mhd_THREADS_KIND_POSIX 434 || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 435 || !mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID 436 || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_ 437 || !mhd_thread_handle_get_native_ptr */ 438 struct mhd_thread_handle_ID_ 439 { 440 mhd_thread_handle handle; /**< To be used in other threads */ 441 mhd_thread_ID ID; /**< To be used in the thread itself */ 442 }; 443 typedef struct mhd_thread_handle_ID_ mhd_thread_handle_ID; 444 #endif /* !mhd_THREADS_KIND_POSIX 445 || !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 446 || !mhd_THREAD_HANDLE_NATIVE_VALUE_INVALID 447 || !MHD_THREAD_ID_NATIVE_VALUE_INVALID_ 448 || !mhd_thread_handle_get_native_ptr */ 449 450 /** 451 * Set the mhd_thread_handle_ID to the invalid value 452 */ 453 #define mhd_thread_handle_ID_set_invalid(hndl_id_ptr) \ 454 (mhd_thread_handle_set_invalid (&((hndl_id_ptr)->handle)), \ 455 mhd_thread_ID_set_invalid (&((hndl_id_ptr)->ID))) 456 457 /** 458 * Check whether the thread handle is valid. 459 * To be used in threads other then the thread specified by the @a hndl_id. 460 */ 461 #define mhd_thread_handle_ID_is_valid_handle(hndl_id) \ 462 mhd_thread_handle_is_valid ((hndl_id).handle) 463 464 /** 465 * Set the native handle in the variable pointed by the @a hndl_id_ptr 466 * to the @a native_val value 467 */ 468 #define mhd_thread_handle_ID_set_native_handle(hndl_id_ptr,native_val) \ 469 mhd_thread_handle_set_native (&((hndl_id_ptr)->handle),native_val) 470 471 #if defined(mhd_thread_handle_get_native_ptr) 472 /** 473 * Get the pointer to the native handle stored the variable pointed by 474 * the @a hndl_id_ptr 475 * @note This macro could not available if direct manipulation of 476 * the native handle is not possible 477 */ 478 # define mhd_thread_handle_ID_get_native_handle_ptr(hndl_id_ptr) \ 479 mhd_thread_handle_get_native_ptr (&((hndl_id_ptr)->handle)) 480 #endif /* mhd_thread_handle_get_native_ptr */ 481 482 /** 483 * Get the native thread handle from the mhd_thread_handle_ID variable. 484 */ 485 #define mhd_thread_handle_ID_get_native_handle(hndl_id) \ 486 mhd_thread_handle_get_native ((hndl_id).handle) 487 488 /** 489 * Check whether the thread ID is valid. 490 * To be used in the thread itself. 491 */ 492 #define mhd_thread_handle_ID_is_valid_ID(hndl_id) \ 493 mhd_thread_ID_is_valid ((hndl_id).ID) 494 495 #if defined(MHD_THREAD_HANDLE_ID_IS_UNION) 496 # if defined(mhd_THREADS_KIND_W32) 497 # error mhd_thread_handle_ID cannot be a union with W32 threads 498 # endif /* mhd_THREADS_KIND_W32 */ 499 /** 500 * Set current thread ID in the variable pointed by the @a hndl_id_ptr 501 */ 502 # define mhd_thread_handle_ID_set_current_thread_ID(hndl_id_ptr) (void) 0 503 #else /* ! MHD_THREAD_HANDLE_ID_IS_UNION */ 504 /** 505 * Set current thread ID in the variable pointed by the @a hndl_id_ptr 506 */ 507 # define mhd_thread_handle_ID_set_current_thread_ID(hndl_id_ptr) \ 508 mhd_thread_ID_set_current_thread (&((hndl_id_ptr)->ID)) 509 #endif /* ! MHD_THREAD_HANDLE_ID_IS_UNION */ 510 511 /** 512 * Check whether provided thread ID matches current thread. 513 * @param ID thread ID to match 514 * @return nonzero on match, zero otherwise 515 */ 516 #define mhd_thread_handle_ID_is_current_thread(hndl_id) \ 517 mhd_thread_ID_is_current_thread ((hndl_id).ID) 518 519 /** 520 * Wait until specified thread is ended and free thread handle on success. 521 * @param hndl_id_ handle with ID to watch 522 * @return nonzero on success, zero otherwise 523 */ 524 #define mhd_thread_handle_ID_join_thread(hndl_id) \ 525 mhd_join_thread (mhd_thread_handle_ID_get_native_handle (hndl_id)) 526 527 528 /** 529 * Create a thread and set the attributes according to our options. 530 * 531 * If thread is created, thread handle must be freed by mhd_join_thread(). 532 * 533 * @param handle_id handle to initialise 534 * @param stack_size size of stack for new thread, 0 for default 535 * @param start_routine main function of thread 536 * @param arg argument for start_routine 537 * @return non-zero on success; zero otherwise (with errno set) 538 */ 539 bool 540 mhd_create_thread (mhd_thread_handle_ID *handle_id, 541 size_t stack_size, 542 mhd_THREAD_START_ROUTINE start_routine, 543 void *arg); 544 545 #ifndef mhd_USE_THREAD_NAME 546 #define mhd_create_named_thread(t,n,s,r,a) mhd_create_thread ((t),(s),(r),(a)) 547 #else /* mhd_USE_THREAD_NAME */ 548 /** 549 * Create a named thread and set the attributes according to our options. 550 * 551 * @param handle_id handle to initialise 552 * @param thread_name name for new thread 553 * @param stack_size size of stack for new thread, 0 for default 554 * @param start_routine main function of thread 555 * @param arg argument for start_routine 556 * @return non-zero on success; zero otherwise 557 */ 558 bool 559 mhd_create_named_thread (mhd_thread_handle_ID *handle_id, 560 const char *thread_name, 561 size_t stack_size, 562 mhd_THREAD_START_ROUTINE start_routine, 563 void *arg); 564 565 #endif /* mhd_USE_THREAD_NAME */ 566 567 #if ! defined(mhd_SEND_SPIPE_SUPPRESS_NEEDED) 568 # define mhd_thread_block_sigpipe() ((void) 0) 569 #else 570 # ifdef HAVE_PTHREAD_SIGMASK 571 /** 572 * Block a SIGPIPE signal in the current thread 573 * 574 * @return 'true' on success, 575 * 'false' otherwise 576 */ 577 MHD_INTERNAL bool 578 mhd_thread_block_sigpipe (void); 579 580 /** 581 * Indicates that function #mhd_thread_block_sigpipe() is available 582 */ 583 # define mhd_HAVE_MHD_THREAD_BLOCK_SIGPIPE 1 584 # endif 585 #endif 586 #endif /* ! MHD_THREADS_H */