我创建了以下程序来创建日志记录线程,并允许其他线程写入由此线程管理的共享缓冲区。奇怪的是,如果我在stopLog
函数中不包含对日志的写入,则日志永远不会关闭,并且线程不会终止。
#include "log.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#define BUFFER_SIZE 128
static pthread_mutex_t logFileMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t logInUse = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t emptyCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t fullCond = PTHREAD_COND_INITIALIZER;
static int bufferIsEmpty;
static int bufferIsFull;
static char buffer[BUFFER_SIZE];
static int in;
static int out;
static int count;
static int stop;
void * logOutput(void * in) {
stop = 0;
bufferIsEmpty = 1;
bufferIsFull = 0;
char ch;
FILE * f = fopen((char *)in, "a");
if (NULL != f) {
fprintf(f, "---------------- Log Opened ----------------\n");
while (!stop) {
pthread_mutex_lock(&logFileMutex);
while (bufferIsEmpty)
pthread_cond_wait(&emptyCond, &logFileMutex);
ch = buffer[out++];
out %= BUFFER_SIZE;
if (--count == 0)
bufferIsEmpty = 1;
bufferIsFull = 0;
fputc(ch, f);
pthread_cond_signal(&fullCond);
pthread_mutex_unlock(&logFileMutex);
}
fprintf(f, "---------------- Log Closed ----------------\n");
fflush(f);
fclose(f);
} else {
fprintf(stderr, "Error opening log file %s\n", (char *)in);
}
pthread_exit(NULL);
}
void writeToLog(char * str) {
pthread_mutex_lock(&logInUse);
for (int i = 0; i <= strlen(str); i++) {
pthread_mutex_lock(&logFileMutex);
while (bufferIsFull)
pthread_cond_wait(&fullCond, &logFileMutex);
if (strlen(str) == i)
buffer[in++] = '\n';
else
buffer[in++] = str[i];
in %= BUFFER_SIZE;
if (++count == (BUFFER_SIZE - 1))
bufferIsFull = 1;
bufferIsEmpty = 0;
usleep(10);
pthread_cond_signal(&emptyCond);
pthread_mutex_unlock(&logFileMutex);
}
pthread_mutex_unlock(&logInUse);
}
void stopLog() {
writeToLog("Stopping log...");
stop = 1;
}
答案 0 :(得分:1)
如果缓冲区为空且logOutput()
上pthread_cond_wait()
被阻止,则设置stop = 1
不会将其唤醒。在下次唤醒之前它不会注意到,写一些日志输出就可以实现。
作为线程之间共享的变量,还需要保护stop
不受同步访问的影响。
您可以通过将logOutput()
中的循环更改为
pthread_mutex_lock(&logFileMutex);
while (!stop)
{
while (!stop && bufferIsEmpty)
pthread_cond_wait(&emptyCond, &logFileMutex);
while (!bufferIsEmpty)
{
ch = buffer[out++];
out %= BUFFER_SIZE;
if (--count == 0)
bufferIsEmpty = 1;
fputc(ch, f);
}
bufferIsFull = 0;
pthread_cond_signal(&fullCond);
}
pthread_mutex_unlock(&logFileMutex);
并将stopLog()
更改为:
void stopLog() {
pthread_mutex_lock(&logFileMutex);
stop = 1;
pthread_cond_signal(&emptyCond);
pthread_mutex_unlock(&logFileMutex);
}
现在,当调用stopLog()
时,logOutput()
将被唤醒,处理在停止和退出的同时发送的任何日志消息。