79 lines
1.8 KiB
Diff
79 lines
1.8 KiB
Diff
|
From 05c3f60fe02370f4c8d15b996bcc8d6f3dc57e12 Mon Sep 17 00:00:00 2001
|
||
|
From: Ludwig Nussel <ludwig.nussel@suse.de>
|
||
|
Date: Thu, 21 Jun 2012 09:09:19 +0200
|
||
|
Subject: [PATCH] fix deadlock
|
||
|
|
||
|
writelog() must not call pthread_yield() with the lock held that the
|
||
|
main thread tries to get to cancel the writer thread. writelog()
|
||
|
on the other hand needs to empty the buffer always to make sure
|
||
|
poll() blocks again an doesn't cause a loop.
|
||
|
---
|
||
|
libconsole.c | 25 +++++++++++++++++--------
|
||
|
1 files changed, 17 insertions(+), 8 deletions(-)
|
||
|
|
||
|
diff --git a/libconsole.c b/libconsole.c
|
||
|
index b962032..54b353a 100644
|
||
|
--- a/libconsole.c
|
||
|
+++ b/libconsole.c
|
||
|
@@ -429,21 +429,28 @@ xout:
|
||
|
|
||
|
static inline void writelog(void)
|
||
|
{
|
||
|
- if (!flog)
|
||
|
+ lock(&llock);
|
||
|
+ if (!flog) { /* log file closed, reset buffer */
|
||
|
+ resetlog();
|
||
|
+ unlock(&llock);
|
||
|
return;
|
||
|
+ }
|
||
|
clearerr(flog);
|
||
|
- lock(&llock);
|
||
|
while (avail > 0) {
|
||
|
size_t ret = (size_t)avail;
|
||
|
|
||
|
if (avail > TRANS_BUFFER_SIZE)
|
||
|
ret = TRANS_BUFFER_SIZE;
|
||
|
|
||
|
- if (!flog || nsigsys)
|
||
|
+ if (!flog || nsigsys) { /* log file closed, reset buffer */
|
||
|
+ resetlog();
|
||
|
break;
|
||
|
+ }
|
||
|
ret = fwrite(head, sizeof(unsigned char), ret, flog);
|
||
|
- if (!ret && ferror(flog))
|
||
|
+ if (!ret && ferror(flog)) { /* cannot write anymore, reset buffer */
|
||
|
+ resetlog();
|
||
|
break;
|
||
|
+ }
|
||
|
head += ret;
|
||
|
|
||
|
if (head >= tail) { /* empty, reset buffer */
|
||
|
@@ -498,8 +505,13 @@ static inline int poll(int msec, mutex_t *outer)
|
||
|
if (err == ETIMEDOUT || err == EBUSY)
|
||
|
ret = 0;
|
||
|
}
|
||
|
- } else
|
||
|
+#if 0
|
||
|
+ } else {
|
||
|
+ unlock(&ljoin);
|
||
|
pthread_yield();
|
||
|
+ lock(&ljoin);
|
||
|
+#endif
|
||
|
+ }
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
@@ -772,9 +784,6 @@ static void *action(void *dummy attribute((unused)))
|
||
|
if (!poll(30, &ljoin))
|
||
|
continue;
|
||
|
|
||
|
- if (!flog)
|
||
|
- break;
|
||
|
-
|
||
|
writelog();
|
||
|
}
|
||
|
unlock(&ljoin);
|
||
|
--
|
||
|
1.7.7
|
||
|
|