C程序只在调试时写入文件

标签 c multithreading file threadpool

我正在编写一个简单的代码来测试线程池。我有一个客户端通过不同的端口向服务器发送数据行。 一些线程接收数据,然后将它们发送给其他线程进行处理。 目前,我所做的唯一处理就是将数据写入文件。

这是工作线程的代码。

void* worker_thread(void* arg){
    int i, workerNum;
    pthread_t worker_id = pthread_self();
    char *ticket = (char*) arg;
    char dumpfile[50];
    for(i=0;i<10;i++)  
        if(pthread_equal(worker_id, id_pool[i]))
        break;
    if(10==i){
        pthread_exit(NULL);
    }
    workerNum = i;
    fprintf(stdout, "Worker [%d] busy\n",workerNum);
    sprintf(dumpfile, "worker_%d.log",workerNum);
    if(strlen(ticket)<4){
        fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);    
        poolStatus[workerNum] = 0;
        pthread_mutex_unlock(&mutexes[workerNum]);
        pthread_exit(NULL); 
    }
    FILE *logFile = fopen(dumpfile, "a+");
    // ticket[strlen(ticket)]
    fprintf(logFile,  "%s\n", ticket);
    fclose(logFile);
    sleep(workerNum+2);
    poolStatus[workerNum] = 0;
    fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);
    pthread_mutex_unlock(&mutexes[workerNum]);
    pthread_exit(NULL); 
}

当我通过调试器(GDB,在 Linux 下)运行时,代码可以工作。当我简单地在命令行上运行它时,它会运行但不会创建文件! 您能帮忙吗?

完整代码:

#include <time.h>
#include <errno.h>
#include <netdb.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <strings.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define BUFSIZE     65535
#define NUMWORKERS  10

static pthread_mutex_t mutexes[NUMWORKERS];
pthread_t   id_pool[NUMWORKERS], id_servers[6];
int  serverports[6]         = {22191, 22192, 22193, 7525, 7526, 7527};
char poolStatus[NUMWORKERS] = {0};

void error(char *msg) {
    FILE *logFile = fopen("errorlog.log", "a+");
    fprintf(logFile,  "%s\n", msg);
    fclose(logFile);
    exit(1);
}

void* serverListener(void* arg);
void* worker_thread(void* arg);


int main(){
    int i, t_err[6];
    for(i=0; i< NUMWORKERS; i++)
        pthread_mutex_init(&mutexes[i],NULL);
    for(i=0; i<6; i++){
        t_err[i] = pthread_create(&id_servers[i], NULL, serverListener, NULL);
    }
    pthread_join(id_servers[5], NULL);
    return 0;
}


void* serverListener(void* arg){
    int                parentfd, childfd;     // parent socket & child socket
    int                portno, clientlen;     // port number and size of client address
    struct sockaddr_in serveraddr;
    struct sockaddr_in clientaddr;// server and client addresses
    struct hostent     *hostp;                // client host info
    char               buf[BUFSIZE];          // message buffer
    char               *hostaddrp;            // dotted decimal host addr string
    int                optval, n;             // flag value for setsockopt and message byte size
    unsigned int       CLOCKREF, CLOCKCOUNT;
    pthread_t          id = pthread_self();   // own thread id
    int                threadNumber, i=0;     // thread number linked to ort to listen to.
    char               dumpfile[50];
    for(i=0; i<6; i++) if(pthread_equal(id, id_servers[i])) break;
    threadNumber = i;

    portno = serverports[threadNumber];
    sprintf(dumpfile, "receiver_%d.log",portno);
    // socket: create the parent socket 
    parentfd = socket(AF_INET, SOCK_STREAM, 0);
    if (parentfd < 0) 
        error("ERROR opening socket");

    optval = 1;
    setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));

    // build the server's Internet address
    bzero((char *) &serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;

    // let the system figure out our IP address
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    // this is the port we will listen on
    serveraddr.sin_port = htons((unsigned short)portno);

    // bind: associate the parent socket with a port 
    if (bind(parentfd, (struct sockaddr *) &serveraddr, 
        sizeof(serveraddr)) < 0) 
        error("ERROR on binding");

    // listen: make this socket ready to accept connection requests 
    if (listen(parentfd, 5) < 0) /* allow 5 requests to queue up */ 
        error("ERROR on listen");

    // main loop: wait for a connection request
    clientlen = sizeof(clientaddr);
    while (1) {
        // accept: wait for a connection request 
        childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen);
        if (childfd < 0) 
        error("ERROR on accept");

        // gethostbyaddr: determine who sent the message 
        hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, 
                sizeof(clientaddr.sin_addr.s_addr), AF_INET);
        if (hostp == NULL)
        error("ERROR on gethostbyaddr");
        hostaddrp = inet_ntoa(clientaddr.sin_addr);
        if (hostaddrp == NULL)
        error("ERROR on inet_ntoa\n");
        fprintf(stdout, "server established connection with %s (%s)\n", hostp->h_name, hostaddrp);

        // read: read input string from the client
        CLOCKREF = (unsigned int)time(NULL); 
        int counter = 0;
        while(1){
            CLOCKCOUNT = (unsigned int)time(NULL) - CLOCKREF; 
            bzero(buf, BUFSIZE);
            n = read(childfd, buf, BUFSIZE);
            if (n < 0)        error("ERROR reading from socket");
            if(0==n) counter++;
            if(3<=counter) {
                close(childfd);
                return;
            }

            int busyWorker = 1;
            i = 0;
            while(busyWorker){
                if(i>=NUMWORKERS) i = 0;

                if(pthread_mutex_trylock(&mutexes[i])==0){ // not locked, can be used
                    fprintf(stdout, "port [%d] sends to thread [%d]\n", portno, i);
                    pthread_create(&id_pool[i], NULL, worker_thread, (void*)buf);
                    busyWorker = 0;
                    break;
                }
                i++;
            }
        }
        close(childfd);
    }
}

void* worker_thread(void* arg){
    int i, workerNum;
    pthread_t worker_id = pthread_self();
    char *ticket = (char*) arg;
    char dumpfile[50];
    for(i=0;i<10;i++)  
        if(pthread_equal(worker_id, id_pool[i]))
        break;
    if(10==i){
        pthread_exit(NULL);
    }
    workerNum = i;
    fprintf(stdout, "Worker [%d] busy\n",workerNum);
    sprintf(dumpfile, "worker_%d.log",workerNum);
    if(strlen(ticket)<4){
        fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);    
        poolStatus[workerNum] = 0;
        pthread_mutex_unlock(&mutexes[workerNum]);
        pthread_exit(NULL); 
    }
    FILE *logFile = fopen(dumpfile, "a+");
    // ticket[strlen(ticket)]
    fprintf(logFile,  "%s\n", ticket);
    fclose(logFile);
    sleep(workerNum+2);
    poolStatus[workerNum] = 0;
    fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);
    pthread_mutex_unlock(&mutexes[workerNum]);
    pthread_exit(NULL); 
}

最佳答案

我相信我已经找到问题了!!

为了将消息从 serverListener 线程传递到 worker_thread,我使用了指向用于从套接字读取的缓冲区的指针。问题是,在 worker_thread 可以处理它之前,serverListener 已将值重置为零( bzero(buf, BUFSIZE) )!鉴于 worker_thread 必须仅在大小大于 4 时写入文件,因此它不会写入。 所以为了解决我的问题,我替换了该行:

pthread_create(&id_pool[i], NULL, worker_thread, (void*)buf);

作者:

char *msg2send = strdup(buf);
pthread_create(&id_pool[i], NULL, worker_thread, (void*)msg2send);

它成功了! 但仍然没有真正解释为什么它可以在 Debug模式下创建文件......

关于C程序只在调试时写入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44521354/

相关文章:

c - 将 execvp 的输出重定向到 C 中的文件中

c - 同一信号的多个信号处理程序,例如西格勒姆

java - 使用java读取制表符分隔文件的快速有效方法

c - 有没有办法让 printf 只引用一个变量的一个实例,用于相同的转换字符重复 x 次?

c udp聊天测试

java - 让线程只是等待

c# - 连续读取 CF 上的多个 TCP 连接

java - 如果返回值取决于阻塞操作的结果,方法是否会阻塞?

scala - 如何获取 Scala 中的当前(工作)目录?

file - 如何将Base64字符串保存到文件并使用Flutter查看