--- libconsole.c +++ libconsole.c 2012-08-02 11:45:26.456510085 +0000 @@ -358,7 +358,9 @@ static void sigio(int sig) */ typedef struct _mutex { - int locked; + volatile int locked; + volatile int canceled; + volatile int used; pthread_mutex_t mutex; pthread_t thread; } mutex_t; @@ -380,8 +382,8 @@ static inline void unlock(mutex_t *mutex } } -static mutex_t llock = { 0, PTHREAD_MUTEX_INITIALIZER, 0 }; -static mutex_t ljoin = { 0, PTHREAD_MUTEX_INITIALIZER, 0 }; +static mutex_t llock = { 0, 0, 1, PTHREAD_MUTEX_INITIALIZER, 0 }; +static mutex_t ljoin = { 0, 0, 1, PTHREAD_MUTEX_INITIALIZER, 0 }; static pthread_cond_t lcond = PTHREAD_COND_INITIALIZER; static pthread_t lthread; static volatile int running; @@ -429,10 +431,14 @@ xout: static inline void writelog(void) { + int oldstate; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); lock(&llock); if (!flog) { /* log file closed, reset buffer */ resetlog(); unlock(&llock); + pthread_setcancelstate(oldstate, NULL); return; } clearerr(flog); @@ -468,11 +474,12 @@ static inline void writelog(void) fflush(flog); fdatasync(fileno(flog)); } + pthread_setcancelstate(oldstate, NULL); } static inline void flushlog(void) { - if (running) pthread_cond_broadcast(&lcond); + if (ljoin.canceled == 0) pthread_cond_broadcast(&lcond); } static inline int poll(int msec, mutex_t *outer) @@ -495,11 +502,13 @@ static inline int poll(int msec, mutex_t abstime.tv_nsec = now.tv_usec * 1000; do { - int locked = outer->locked; /* Note: pthread_cond_timedwait() atomically unlocks the mutex */ - outer->locked = 0; - err = pthread_cond_timedwait(&lcond, &outer->mutex, &abstime); - outer->locked = locked; + if (outer->canceled == 0) { + volatile int locked = outer->locked; + outer->locked = 0; + err = pthread_cond_timedwait(&lcond, &outer->mutex, &abstime); + outer->locked = locked; + } } while (err == EINTR); if (err == ETIMEDOUT || err == EBUSY) @@ -507,9 +516,9 @@ static inline int poll(int msec, mutex_t } #if 0 } else { - unlock(&ljoin); + unlock(&outer->mutex); pthread_yield(); - lock(&ljoin); + lock(&outer->mutex); #endif } @@ -789,6 +798,7 @@ static void *action(void *dummy attribut unlock(&ljoin); (void)pthread_sigmask(SIG_SETMASK, &save_oldset, NULL); + ljoin.used = 0; return NULL; } @@ -1004,6 +1014,8 @@ void closeIO(void) (void)tcdrain(c->fd); /* Hold in sync with console */ } + flushlog(); + do { /* * Repeat this as long as required, @@ -1020,14 +1032,19 @@ void closeIO(void) more_input(&timeout, 1); (void)tcdrain(fdread); + flushlog(); + } while (timeout.tv_sec || timeout.tv_nsec); if (running) { lock(&ljoin); running = 0; unlock(&ljoin); - flushlog(); - pthread_cancel(lthread); + ljoin.canceled = 1; + pthread_cond_broadcast(&lcond); + pthread_yield(); + if (ljoin.used && lthread) + pthread_cancel(lthread); } if (flog) {