123 lines
3.0 KiB
Plaintext
123 lines
3.0 KiB
Plaintext
--- 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) {
|