1 /*
2  * barrier -- mouse and keyboard sharing utility
3  * Copyright (C) 2012-2016 Symless Ltd.
4  * Copyright (C) 2002 Chris Schoeneman
5  *
6  * This package is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * found in the file LICENSE that should have accompanied this file.
9  *
10  * This package is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "arch/unix/ArchMultithreadPosix.h"
20 
21 #include "arch/Arch.h"
22 #include "arch/XArch.h"
23 
24 #include <signal.h>
25 #if TIME_WITH_SYS_TIME
26 #    include <sys/time.h>
27 #    include <time.h>
28 #else
29 #    if HAVE_SYS_TIME_H
30 #        include <sys/time.h>
31 #    else
32 #        include <time.h>
33 #    endif
34 #endif
35 #include <cerrno>
36 
37 #define SIGWAKEUP SIGUSR1
38 
39 static
40 void
setSignalSet(sigset_t * sigset)41 setSignalSet(sigset_t* sigset)
42 {
43     sigemptyset(sigset);
44     sigaddset(sigset, SIGHUP);
45     sigaddset(sigset, SIGINT);
46     sigaddset(sigset, SIGTERM);
47     sigaddset(sigset, SIGUSR2);
48 }
49 
50 //
51 // ArchThreadImpl
52 //
53 
54 class ArchThreadImpl {
55 public:
56     ArchThreadImpl();
57 
58 public:
59     int                    m_refCount;
60     IArchMultithread::ThreadID        m_id;
61     pthread_t            m_thread;
62     IArchMultithread::ThreadFunc    m_func;
63     void*                m_userData;
64     bool                m_cancel;
65     bool                m_cancelling;
66     bool                m_exited;
67     void*                m_result;
68     void*                m_networkData;
69 };
70 
ArchThreadImpl()71 ArchThreadImpl::ArchThreadImpl() :
72     m_refCount(1),
73     m_id(0),
74     m_func(NULL),
75     m_userData(NULL),
76     m_cancel(false),
77     m_cancelling(false),
78     m_exited(false),
79     m_result(NULL),
80     m_networkData(NULL)
81 {
82     // do nothing
83 }
84 
85 
86 //
87 // ArchMultithreadPosix
88 //
89 
90 ArchMultithreadPosix*    ArchMultithreadPosix::s_instance = NULL;
91 
ArchMultithreadPosix()92 ArchMultithreadPosix::ArchMultithreadPosix() :
93     m_newThreadCalled(false),
94     m_nextID(0)
95 {
96     assert(s_instance == NULL);
97 
98     s_instance = this;
99 
100     // no signal handlers
101     for (size_t i = 0; i < kNUM_SIGNALS; ++i) {
102         m_signalFunc[i]     = NULL;
103         m_signalUserData[i] = NULL;
104     }
105 
106     // create thread for calling (main) thread and add it to our
107     // list.  no need to lock the mutex since we're the only thread.
108     m_mainThread           = new ArchThreadImpl;
109     m_mainThread->m_thread = pthread_self();
110     insert(m_mainThread);
111 
112     // install SIGWAKEUP handler.  this causes SIGWAKEUP to interrupt
113     // system calls.  we use that when cancelling a thread to force it
114     // to wake up immediately if it's blocked in a system call.  we
115     // won't need this until another thread is created but it's fine
116     // to install it now.
117     struct sigaction act;
118     sigemptyset(&act.sa_mask);
119 # if defined(SA_INTERRUPT)
120     act.sa_flags   = SA_INTERRUPT;
121 # else
122     act.sa_flags   = 0;
123 # endif
124     act.sa_handler = &threadCancel;
125     sigaction(SIGWAKEUP, &act, NULL);
126 
127     // set desired signal dispositions.  let SIGWAKEUP through but
128     // ignore SIGPIPE (we'll handle EPIPE).
129     sigset_t sigset;
130     sigemptyset(&sigset);
131     sigaddset(&sigset, SIGWAKEUP);
132     pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
133     sigemptyset(&sigset);
134     sigaddset(&sigset, SIGPIPE);
135     pthread_sigmask(SIG_BLOCK, &sigset, NULL);
136 }
137 
~ArchMultithreadPosix()138 ArchMultithreadPosix::~ArchMultithreadPosix()
139 {
140     assert(s_instance != NULL);
141 
142     s_instance = NULL;
143 }
144 
145 void
setNetworkDataForCurrentThread(void * data)146 ArchMultithreadPosix::setNetworkDataForCurrentThread(void* data)
147 {
148     std::lock_guard<std::mutex> lock(m_threadMutex);
149     ArchThreadImpl* thread = find(pthread_self());
150     thread->m_networkData = data;
151 }
152 
153 void*
getNetworkDataForThread(ArchThread thread)154 ArchMultithreadPosix::getNetworkDataForThread(ArchThread thread)
155 {
156     std::lock_guard<std::mutex> lock(m_threadMutex);
157     return thread->m_networkData;
158 }
159 
160 ArchMultithreadPosix*
getInstance()161 ArchMultithreadPosix::getInstance()
162 {
163     return s_instance;
164 }
165 
166 ArchCond
newCondVar()167 ArchMultithreadPosix::newCondVar()
168 {
169     ArchCondImpl* cond = new ArchCondImpl;
170     int status = pthread_cond_init(&cond->m_cond, NULL);
171     (void)status;
172     assert(status == 0);
173     return cond;
174 }
175 
176 void
closeCondVar(ArchCond cond)177 ArchMultithreadPosix::closeCondVar(ArchCond cond)
178 {
179     int status = pthread_cond_destroy(&cond->m_cond);
180     (void)status;
181     assert(status == 0);
182     delete cond;
183 }
184 
185 void
signalCondVar(ArchCond cond)186 ArchMultithreadPosix::signalCondVar(ArchCond cond)
187 {
188     int status = pthread_cond_signal(&cond->m_cond);
189     (void)status;
190     assert(status == 0);
191 }
192 
193 void
broadcastCondVar(ArchCond cond)194 ArchMultithreadPosix::broadcastCondVar(ArchCond cond)
195 {
196     int status = pthread_cond_broadcast(&cond->m_cond);
197     (void)status;
198     assert(status == 0);
199 }
200 
201 bool
waitCondVar(ArchCond cond,ArchMutex mutex,double timeout)202 ArchMultithreadPosix::waitCondVar(ArchCond cond,
203                             ArchMutex mutex, double timeout)
204 {
205     // we can't wait on a condition variable and also wake it up for
206     // cancellation since we don't use posix cancellation.  so we
207     // must wake up periodically to check for cancellation.  we
208     // can't simply go back to waiting after the check since the
209     // condition may have changed and we'll have lost the signal.
210     // so we have to return to the caller.  since the caller will
211     // always check for spurious wakeups the only drawback here is
212     // performance:  we're waking up a lot more than desired.
213     static const double maxCancellationLatency = 0.1;
214     if (timeout < 0.0 || timeout > maxCancellationLatency) {
215         timeout = maxCancellationLatency;
216     }
217 
218     // see if we should cancel this thread
219     testCancelThread();
220 
221     // get final time
222     struct timeval now;
223     gettimeofday(&now, NULL);
224     struct timespec finalTime;
225     finalTime.tv_sec   = now.tv_sec;
226     finalTime.tv_nsec  = now.tv_usec * 1000;
227     long timeout_sec   = (long)timeout;
228     long timeout_nsec  = (long)(1.0e+9 * (timeout - timeout_sec));
229     finalTime.tv_sec  += timeout_sec;
230     finalTime.tv_nsec += timeout_nsec;
231     if (finalTime.tv_nsec >= 1000000000) {
232         finalTime.tv_nsec -= 1000000000;
233         finalTime.tv_sec  += 1;
234     }
235 
236     // wait
237     int status = pthread_cond_timedwait(&cond->m_cond,
238                             &mutex->m_mutex, &finalTime);
239 
240     // check for cancel again
241     testCancelThread();
242 
243     switch (status) {
244     case 0:
245         // success
246         return true;
247 
248     case ETIMEDOUT:
249         return false;
250 
251     default:
252         assert(0 && "condition variable wait error");
253         return false;
254     }
255 }
256 
257 ArchMutex
newMutex()258 ArchMultithreadPosix::newMutex()
259 {
260     pthread_mutexattr_t attr;
261     int status = pthread_mutexattr_init(&attr);
262     assert(status == 0);
263     ArchMutexImpl* mutex = new ArchMutexImpl;
264     status = pthread_mutex_init(&mutex->m_mutex, &attr);
265     assert(status == 0);
266     return mutex;
267 }
268 
269 void
closeMutex(ArchMutex mutex)270 ArchMultithreadPosix::closeMutex(ArchMutex mutex)
271 {
272     int status = pthread_mutex_destroy(&mutex->m_mutex);
273     (void)status;
274     assert(status == 0);
275     delete mutex;
276 }
277 
278 void
lockMutex(ArchMutex mutex)279 ArchMultithreadPosix::lockMutex(ArchMutex mutex)
280 {
281     int status = pthread_mutex_lock(&mutex->m_mutex);
282 
283     switch (status) {
284     case 0:
285         // success
286         return;
287 
288     case EDEADLK:
289         assert(0 && "lock already owned");
290         break;
291 
292     case EAGAIN:
293         assert(0 && "too many recursive locks");
294         break;
295 
296     default:
297         assert(0 && "unexpected error");
298         break;
299     }
300 }
301 
302 void
unlockMutex(ArchMutex mutex)303 ArchMultithreadPosix::unlockMutex(ArchMutex mutex)
304 {
305     int status = pthread_mutex_unlock(&mutex->m_mutex);
306 
307     switch (status) {
308     case 0:
309         // success
310         return;
311 
312     case EPERM:
313         assert(0 && "thread doesn't own a lock");
314         break;
315 
316     default:
317         assert(0 && "unexpected error");
318         break;
319     }
320 }
321 
322 ArchThread
newThread(ThreadFunc func,void * data)323 ArchMultithreadPosix::newThread(ThreadFunc func, void* data)
324 {
325     assert(func != NULL);
326 
327     // initialize signal handler.  we do this here instead of the
328     // constructor so we can avoid daemonizing (using fork())
329     // when there are multiple threads.  clients can safely
330     // use condition variables and mutexes before creating a
331     // new thread and they can safely use the only thread
332     // they have access to, the main thread, so they really
333     // can't tell the difference.
334     if (!m_newThreadCalled) {
335         m_newThreadCalled = true;
336         startSignalHandler();
337     }
338 
339     // note that the child thread will wait until we release this mutex
340     std::lock_guard<std::mutex> lock(m_threadMutex);
341 
342     // create thread impl for new thread
343     ArchThreadImpl* thread = new ArchThreadImpl;
344     thread->m_func          = func;
345     thread->m_userData      = data;
346 
347     // create the thread.  pthread_create() on RedHat 7.2 smp fails
348     // if passed a NULL attr so use a default attr.
349     pthread_attr_t attr;
350     int status = pthread_attr_init(&attr);
351     if (status == 0) {
352         status = pthread_create(&thread->m_thread, &attr,
353                             &ArchMultithreadPosix::threadFunc, thread);
354         pthread_attr_destroy(&attr);
355     }
356 
357     // check if thread was started
358     if (status != 0) {
359         // failed to start thread so clean up
360         delete thread;
361         thread = NULL;
362     }
363     else {
364         // add thread to list
365         insert(thread);
366 
367         // increment ref count to account for the thread itself
368         refThread(thread);
369     }
370 
371     return thread;
372 }
373 
374 ArchThread
newCurrentThread()375 ArchMultithreadPosix::newCurrentThread()
376 {
377     std::lock_guard<std::mutex> lock(m_threadMutex);
378 
379     ArchThreadImpl* thread = find(pthread_self());
380     assert(thread != NULL);
381     return thread;
382 }
383 
384 void
closeThread(ArchThread thread)385 ArchMultithreadPosix::closeThread(ArchThread thread)
386 {
387     assert(thread != NULL);
388 
389     // decrement ref count and clean up thread if no more references
390     if (--thread->m_refCount == 0) {
391         // detach from thread (unless it's the main thread)
392         if (thread->m_func != NULL) {
393             pthread_detach(thread->m_thread);
394         }
395 
396         // remove thread from list
397         {
398             std::lock_guard<std::mutex> lock(m_threadMutex);
399             assert(findNoRef(thread->m_thread) == thread);
400             erase(thread);
401         }
402 
403         // done with thread
404         delete thread;
405     }
406 }
407 
408 ArchThread
copyThread(ArchThread thread)409 ArchMultithreadPosix::copyThread(ArchThread thread)
410 {
411     refThread(thread);
412     return thread;
413 }
414 
415 void
cancelThread(ArchThread thread)416 ArchMultithreadPosix::cancelThread(ArchThread thread)
417 {
418     assert(thread != NULL);
419 
420     // set cancel and wakeup flags if thread can be cancelled
421     bool wakeup = false;
422 
423     {
424         std::lock_guard<std::mutex> lock(m_threadMutex);
425         if (!thread->m_exited && !thread->m_cancelling) {
426             thread->m_cancel = true;
427             wakeup = true;
428         }
429     }
430 
431     // force thread to exit system calls if wakeup is true
432     if (wakeup) {
433         pthread_kill(thread->m_thread, SIGWAKEUP);
434     }
435 }
436 
437 void
setPriorityOfThread(ArchThread thread,int)438 ArchMultithreadPosix::setPriorityOfThread(ArchThread thread, int /*n*/)
439 {
440     assert(thread != NULL);
441 
442     // FIXME
443 }
444 
445 void
testCancelThread()446 ArchMultithreadPosix::testCancelThread()
447 {
448     // find current thread
449     ArchThreadImpl* thread = nullptr;
450     {
451         std::lock_guard<std::mutex> lock(m_threadMutex);
452         thread = findNoRef(pthread_self());
453     }
454 
455     // test cancel on thread
456     testCancelThreadImpl(thread);
457 }
458 
459 bool
wait(ArchThread target,double timeout)460 ArchMultithreadPosix::wait(ArchThread target, double timeout)
461 {
462     assert(target != NULL);
463 
464     ArchThreadImpl* self = nullptr;
465 
466     {
467         std::lock_guard<std::mutex> lock(m_threadMutex);
468 
469         // find current thread
470         self = findNoRef(pthread_self());
471 
472         // ignore wait if trying to wait on ourself
473         if (target == self) {
474             return false;
475         }
476 
477         // ref the target so it can't go away while we're watching it
478         refThread(target);
479     }
480 
481     try {
482         // do first test regardless of timeout
483         testCancelThreadImpl(self);
484         if (isExitedThread(target)) {
485             closeThread(target);
486             return true;
487         }
488 
489         // wait and repeat test if there's a timeout
490         if (timeout != 0.0) {
491             const double start = ARCH->time();
492             do {
493                 // wait a little
494                 ARCH->sleep(0.05);
495 
496                 // repeat test
497                 testCancelThreadImpl(self);
498                 if (isExitedThread(target)) {
499                     closeThread(target);
500                     return true;
501                 }
502 
503                 // repeat wait and test until timed out
504             } while (timeout < 0.0 || (ARCH->time() - start) <= timeout);
505         }
506 
507         closeThread(target);
508         return false;
509     }
510     catch (...) {
511         closeThread(target);
512         throw;
513     }
514 }
515 
516 bool
isSameThread(ArchThread thread1,ArchThread thread2)517 ArchMultithreadPosix::isSameThread(ArchThread thread1, ArchThread thread2)
518 {
519     return (thread1 == thread2);
520 }
521 
522 bool
isExitedThread(ArchThread thread)523 ArchMultithreadPosix::isExitedThread(ArchThread thread)
524 {
525     std::lock_guard<std::mutex> lock(m_threadMutex);
526     return thread->m_exited;
527 }
528 
529 void*
getResultOfThread(ArchThread thread)530 ArchMultithreadPosix::getResultOfThread(ArchThread thread)
531 {
532     std::lock_guard<std::mutex> lock(m_threadMutex);
533     return thread->m_result;
534 }
535 
536 IArchMultithread::ThreadID
getIDOfThread(ArchThread thread)537 ArchMultithreadPosix::getIDOfThread(ArchThread thread)
538 {
539     return thread->m_id;
540 }
541 
542 void
setSignalHandler(ESignal signal,SignalFunc func,void * userData)543 ArchMultithreadPosix::setSignalHandler(
544                 ESignal signal, SignalFunc func, void* userData)
545 {
546     std::lock_guard<std::mutex> lock(m_threadMutex);
547     m_signalFunc[signal]     = func;
548     m_signalUserData[signal] = userData;
549 }
550 
551 void
raiseSignal(ESignal signal)552 ArchMultithreadPosix::raiseSignal(ESignal signal)
553 {
554     std::lock_guard<std::mutex> lock(m_threadMutex);
555     if (m_signalFunc[signal] != NULL) {
556         m_signalFunc[signal](signal, m_signalUserData[signal]);
557         pthread_kill(m_mainThread->m_thread, SIGWAKEUP);
558     }
559     else if (signal == kINTERRUPT || signal == kTERMINATE) {
560         ARCH->cancelThread(m_mainThread);
561     }
562 }
563 
564 void
startSignalHandler()565 ArchMultithreadPosix::startSignalHandler()
566 {
567     // set signal mask.  the main thread blocks these signals and
568     // the signal handler thread will listen for them.
569     sigset_t sigset, oldsigset;
570     setSignalSet(&sigset);
571     pthread_sigmask(SIG_BLOCK, &sigset, &oldsigset);
572 
573     // fire up the INT and TERM signal handler thread.  we could
574     // instead arrange to catch and handle these signals but
575     // we'd be unable to cancel the main thread since no pthread
576     // calls are allowed in a signal handler.
577     pthread_attr_t attr;
578     int status = pthread_attr_init(&attr);
579     if (status == 0) {
580         status = pthread_create(&m_signalThread, &attr,
581                             &ArchMultithreadPosix::threadSignalHandler,
582                             NULL);
583         pthread_attr_destroy(&attr);
584     }
585     if (status != 0) {
586         // can't create thread to wait for signal so don't block
587         // the signals.
588         pthread_sigmask(SIG_UNBLOCK, &oldsigset, NULL);
589     }
590 }
591 
592 ArchThreadImpl*
find(pthread_t thread)593 ArchMultithreadPosix::find(pthread_t thread)
594 {
595     ArchThreadImpl* impl = findNoRef(thread);
596     if (impl != NULL) {
597         refThread(impl);
598     }
599     return impl;
600 }
601 
602 ArchThreadImpl*
findNoRef(pthread_t thread)603 ArchMultithreadPosix::findNoRef(pthread_t thread)
604 {
605     // linear search
606     for (ThreadList::const_iterator index  = m_threadList.begin();
607                                      index != m_threadList.end(); ++index) {
608         if ((*index)->m_thread == thread) {
609             return *index;
610         }
611     }
612     return NULL;
613 }
614 
615 void
insert(ArchThreadImpl * thread)616 ArchMultithreadPosix::insert(ArchThreadImpl* thread)
617 {
618     assert(thread != NULL);
619 
620     // thread shouldn't already be on the list
621     assert(findNoRef(thread->m_thread) == NULL);
622 
623     // set thread id.  note that we don't worry about m_nextID
624     // wrapping back to 0 and duplicating thread ID's since the
625     // likelihood of barrier running that long is vanishingly
626     // small.
627     thread->m_id = ++m_nextID;
628 
629     // append to list
630     m_threadList.push_back(thread);
631 }
632 
633 void
erase(ArchThreadImpl * thread)634 ArchMultithreadPosix::erase(ArchThreadImpl* thread)
635 {
636     for (ThreadList::iterator index  = m_threadList.begin();
637                                index != m_threadList.end(); ++index) {
638         if (*index == thread) {
639             m_threadList.erase(index);
640             break;
641         }
642     }
643 }
644 
645 void
refThread(ArchThreadImpl * thread)646 ArchMultithreadPosix::refThread(ArchThreadImpl* thread)
647 {
648     assert(thread != NULL);
649     assert(findNoRef(thread->m_thread) != NULL);
650     ++thread->m_refCount;
651 }
652 
653 void
testCancelThreadImpl(ArchThreadImpl * thread)654 ArchMultithreadPosix::testCancelThreadImpl(ArchThreadImpl* thread)
655 {
656     assert(thread != NULL);
657 
658     std::lock_guard<std::mutex> lock(m_threadMutex);
659 
660     // update cancel state
661     bool cancel = false;
662     if (thread->m_cancel && !thread->m_cancelling) {
663         thread->m_cancelling = true;
664         thread->m_cancel     = false;
665         cancel               = true;
666     }
667 
668     // unwind thread's stack if cancelling
669     if (cancel) {
670         throw XThreadCancel();
671     }
672 }
673 
674 void*
threadFunc(void * vrep)675 ArchMultithreadPosix::threadFunc(void* vrep)
676 {
677     // get the thread
678     ArchThreadImpl* thread = static_cast<ArchThreadImpl*>(vrep);
679 
680     // setup pthreads
681     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
682     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
683 
684     // run thread
685     s_instance->doThreadFunc(thread);
686 
687     // terminate the thread
688     return NULL;
689 }
690 
691 void
doThreadFunc(ArchThread thread)692 ArchMultithreadPosix::doThreadFunc(ArchThread thread)
693 {
694     // default priority is slightly below normal
695     setPriorityOfThread(thread, 1);
696 
697     // wait for parent to initialize this object
698     {
699         std::lock_guard<std::mutex> lock(m_threadMutex);
700     }
701 
702     void* result = NULL;
703     try {
704         // go
705         result = (*thread->m_func)(thread->m_userData);
706     }
707 
708     catch (XThreadCancel&) {
709         // client called cancel()
710     }
711     catch (...) {
712         // note -- don't catch (...) to avoid masking bugs
713         {
714             std::lock_guard<std::mutex> lock(m_threadMutex);
715             thread->m_exited = true;
716         }
717         closeThread(thread);
718         throw;
719     }
720 
721     // thread has exited
722     {
723         std::lock_guard<std::mutex> lock(m_threadMutex);
724         thread->m_result = result;
725         thread->m_exited = true;
726     }
727 
728     // done with thread
729     closeThread(thread);
730 }
731 
732 void
threadCancel(int)733 ArchMultithreadPosix::threadCancel(int)
734 {
735     // do nothing
736 }
737 
738 void*
threadSignalHandler(void *)739 ArchMultithreadPosix::threadSignalHandler(void*)
740 {
741     // detach
742     pthread_detach(pthread_self());
743 
744     // add signal to mask
745     sigset_t sigset;
746     setSignalSet(&sigset);
747 
748     // also wait on SIGABRT.  on linux (others?) this thread (process)
749     // will persist after all the other threads evaporate due to an
750     // assert unless we wait on SIGABRT.  that means our resources (like
751     // the socket we're listening on) are not released and never will be
752     // until the lingering thread is killed.  i don't know why sigwait()
753     // should protect the thread from being killed.  note that sigwait()
754     // doesn't actually return if we receive SIGABRT and, for some
755     // reason, we don't have to block SIGABRT.
756     sigaddset(&sigset, SIGABRT);
757 
758     // we exit the loop via thread cancellation in sigwait()
759     for (;;) {
760         // wait
761 #if HAVE_POSIX_SIGWAIT
762         int signal = 0;
763         sigwait(&sigset, &signal);
764 #else
765         sigwait(&sigset);
766 #endif
767 
768         // if we get here then the signal was raised
769         switch (signal) {
770         case SIGINT:
771             ARCH->raiseSignal(kINTERRUPT);
772             break;
773 
774         case SIGTERM:
775             ARCH->raiseSignal(kTERMINATE);
776             break;
777 
778         case SIGHUP:
779             ARCH->raiseSignal(kHANGUP);
780             break;
781 
782         case SIGUSR2:
783             ARCH->raiseSignal(kUSER);
784             break;
785 
786         default:
787             // ignore
788             break;
789         }
790     }
791 
792     return NULL;
793 }
794