|  | // Copyright 2015 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // +build !windows | 
|  |  | 
|  | #include <errno.h> | 
|  | #include <signal.h> | 
|  | #include <stdlib.h> | 
|  | #include <pthread.h> | 
|  | #include <stdio.h> | 
|  | #include <time.h> | 
|  | #include <unistd.h> | 
|  |  | 
|  | extern void IntoGoAndBack(); | 
|  |  | 
|  | int CheckBlocked() { | 
|  | sigset_t mask; | 
|  | sigprocmask(SIG_BLOCK, NULL, &mask); | 
|  | return sigismember(&mask, SIGIO); | 
|  | } | 
|  |  | 
|  | static void* sigthreadfunc(void* unused) { | 
|  | sigset_t mask; | 
|  | sigemptyset(&mask); | 
|  | sigaddset(&mask, SIGIO); | 
|  | sigprocmask(SIG_BLOCK, &mask, NULL); | 
|  | IntoGoAndBack(); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | int RunSigThread() { | 
|  | int tries; | 
|  | pthread_t thread; | 
|  | int r; | 
|  | struct timespec ts; | 
|  |  | 
|  | for (tries = 0; tries < 20; tries++) { | 
|  | r = pthread_create(&thread, NULL, &sigthreadfunc, NULL); | 
|  | if (r == 0) { | 
|  | return pthread_join(thread, NULL); | 
|  | } | 
|  | if (r != EAGAIN) { | 
|  | return r; | 
|  | } | 
|  | ts.tv_sec = 0; | 
|  | ts.tv_nsec = (tries + 1) * 1000 * 1000; // Milliseconds. | 
|  | nanosleep(&ts, NULL); | 
|  | } | 
|  | return EAGAIN; | 
|  | } |