Fix and factor out ether_exit(). Pitifully, MacOS X 10.2 does not make select()

a cancellation point when it is passed a NULL timeout. Workarounded in
receive_func() with a full inline of poll_fd() + pthread_testcancel().
This commit is contained in:
gbeauche 2005-05-15 17:22:12 +00:00
parent 71c3199a42
commit 02714e46a8
2 changed files with 30 additions and 27 deletions

View File

@ -195,7 +195,7 @@ AC_CHECK_LIB(pthread, pthread_create, , [
if [[ "x$HAVE_PTHREADS" = "xyes" ]]; then if [[ "x$HAVE_PTHREADS" = "xyes" ]]; then
AC_DEFINE(HAVE_PTHREADS, 1, [Define if pthreads are available.]) AC_DEFINE(HAVE_PTHREADS, 1, [Define if pthreads are available.])
fi fi
AC_CHECK_FUNCS(pthread_cancel) AC_CHECK_FUNCS(pthread_cancel pthread_testcancel)
AC_CHECK_FUNCS(pthread_mutexattr_setprotocol) AC_CHECK_FUNCS(pthread_mutexattr_setprotocol)
AC_CHECK_FUNCS(pthread_mutexattr_settype) AC_CHECK_FUNCS(pthread_mutexattr_settype)
AC_CHECK_FUNCS(pthread_mutexattr_setpshared) AC_CHECK_FUNCS(pthread_mutexattr_setpshared)

View File

@ -143,14 +143,18 @@ static void stop_thread(void)
{ {
#ifdef HAVE_SLIRP #ifdef HAVE_SLIRP
if (slirp_thread_active) { if (slirp_thread_active) {
#ifdef HAVE_PTHREAD_CANCEL
pthread_cancel(slirp_thread); pthread_cancel(slirp_thread);
#endif
pthread_join(slirp_thread, NULL); pthread_join(slirp_thread, NULL);
slirp_thread_active = false; slirp_thread_active = false;
} }
#endif #endif
if (thread_active) { if (thread_active) {
#ifdef HAVE_PTHREAD_CANCEL
pthread_cancel(ether_thread); pthread_cancel(ether_thread);
#endif
pthread_join(ether_thread, NULL); pthread_join(ether_thread, NULL);
sem_destroy(&int_ack); sem_destroy(&int_ack);
thread_active = false; thread_active = false;
@ -348,13 +352,8 @@ open_error:
void ether_exit(void) void ether_exit(void)
{ {
// Stop reception thread // Stop reception threads
if (thread_active) { stop_thread();
pthread_cancel(ether_thread);
pthread_join(ether_thread, NULL);
sem_destroy(&int_ack);
thread_active = false;
}
// Shut down TUN/TAP interface // Shut down TUN/TAP interface
if (net_if_type == NET_IF_TUNTAP) if (net_if_type == NET_IF_TUNTAP)
@ -546,6 +545,12 @@ void *slirp_receive_func(void *arg)
tv.tv_usec = 16667; tv.tv_usec = 16667;
if (select(nfds + 1, &rfds, &wfds, &xfds, &tv) >= 0) if (select(nfds + 1, &rfds, &wfds, &xfds, &tv) >= 0)
slirp_select_poll(&rfds, &wfds, &xfds); slirp_select_poll(&rfds, &wfds, &xfds);
#ifdef HAVE_PTHREAD_TESTCANCEL
// Explicit cancellation point if select() was not covered
// This seems to be the case on MacOS X 10.2
pthread_testcancel();
#endif
} }
return NULL; return NULL;
} }
@ -561,24 +566,6 @@ void slirp_output(const uint8 *packet, int len)
#endif #endif
/*
* Wait for data to arrive
*/
static inline int poll_fd(int fd)
{
#ifdef HAVE_POLL
struct pollfd pf = {fd, POLLIN, 0};
return poll(&pf, 1, -1);
#else
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
return select(fd + 1, &rfds, NULL, NULL, NULL);
#endif
}
/* /*
* Packet reception thread * Packet reception thread
*/ */
@ -588,7 +575,23 @@ static void *receive_func(void *arg)
for (;;) { for (;;) {
// Wait for packets to arrive // Wait for packets to arrive
int res = poll_fd(fd); #if HAVE_POLL
struct pollfd pf = {fd, POLLIN, 0};
int res = poll(&pf, 1, -1);
#else
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
// A NULL timeout could cause select() to block indefinitely,
// even if it is supposed to be a cancellation point [MacOS X]
struct timeval tv = { 0, 20000 };
int res = select(fd + 1, &rfds, NULL, NULL, &tv);
#ifdef HAVE_PTHREAD_TESTCANCEL
pthread_testcancel();
#endif
if (res == 0 || (res == -1 && errno == EINTR))
continue;
#endif
if (res <= 0) if (res <= 0)
break; break;