具有多线程应用程序的延迟线程的stdout / stderr的QProcess输出

时间:2018-10-24 15:02:13

标签: linux multithreading qt ubuntu qprocess

我的平台:

  • Ubuntu 17.10 32位(Vbox VM)
  • Qt Creator 3.5.1(开放源代码)
  • Qt 5.5.1(GCC 4.9.1 20140922(Red Hat 4.9.1-10),32位

我正在尝试使用 QProcess .start()调用多线程程序(带有参数)。

我的程序在终端上运行良好,即定期在stdout上打印。

使用TextEdit记录我已连接QProcess readyReadStandardOutput / 错误信号的程序的stdout / stderr。

来自程序主线程的stdout / stderr正确显示在TextEdit上,其余输出(来自所有其他线程的输出)未显示。

编辑

在主线程上,HTTP服务器正在侦听。

如果浏览器在URL“ 127.0.0.1:32001”上执行了HTTP请求(端口32001在QT代码中进行了硬编码),则当收到HTTP请求时,程序将附加HTTP数据包和所有未决的输出从另一个线程(moduleThread)到TextEdit,因此可能是刷新的问题。

main.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "http_server.h"

static pthread_t moduleThr;
static pthread_attr_t moduleThread_attr;
static bool one_second_elapsed;
static sem_t oneSecondSem;

void *moduleThread(void *arg0)
{
    bool one_second_elapsed_local;

    while (1)
    {
        sem_wait(&oneSecondSem);
        one_second_elapsed_local = one_second_elapsed;
        one_second_elapsed = false;
        sem_post(&oneSecondSem);

        if (one_second_elapsed_local)
            fprintf(stdout, "Hello world each second!\r\n");

        usleep(50000);
    }
}

static void oneSecElapsed(int signum)
{
    sem_wait(&oneSecondSem);
    one_second_elapsed = true;
    sem_post(&oneSecondSem);
}

static void TIMER_1sec_init(void)
{
    struct sigaction sa;
    struct itimerval timer;

    /* Install timer_handler as the signal handler for SIGALRM. */
    memset (&sa, 0, sizeof (sa));
    sa.sa_handler = &oneSecElapsed;
    sigaction (SIGALRM, &sa, NULL);

    /* Configure the timer to expire after 1 sec... */
    timer.it_value.tv_sec = 1;
    timer.it_value.tv_usec = 0;
    /* ... and every 1 sec after that... */
    timer.it_interval.tv_sec = 1;
    timer.it_interval.tv_usec = 0;
    /* Start a virtual timer. It counts down whenever this process is
    executing. */
    setitimer (ITIMER_REAL, &timer, NULL);
}

/*
 *  ======== main ========
 */
int main(int argc, char *argv[])
{
    const char *tcpport;

    if (argc > 2)
    {
        fprintf(stdout, "id = %s\r\n", argv[1]);
        fprintf(stdout, "tcpport = %s\r\n", argv[2]);
        tcpport = argv[2];
    }
    else
        exit(-1);

    sem_init(&oneSecondSem, 0, 1);
    one_second_elapsed = false;

    /* Create thread quadro manager */
    pthread_attr_init(&moduleThread_attr);
    pthread_attr_setstacksize(&moduleThread_attr, 2048);
    pthread_create(&moduleThr, &moduleThread_attr, moduleThread, NULL);

    TIMER_1sec_init();

    HTTPSERVER_init(tcpport);

    /* should never return */
    return (0);
}

http_server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* memset() */
#include <stdbool.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include "module.h"

typedef struct { char *name, *value; } header_t;
static header_t reqhdr[17] = { {"\0", "\0"} };

//#define PORT    "32001" /* Port to listen on */
#define BACKLOG 10  /* Passed to listen() */

static char *buf;
static char *method;    // "GET" or "POST"
static char *uri;       // "/index.html" things before '?'
static char *qs;        // "a=1&b=2"     things after  '?'
static char *prot;      // "HTTP/1.1"
static char *payload;     // for POST
static int   payload_size;

// get request header
char *request_header(const char* name)
{
    header_t *h = reqhdr;
    while(h->name) {
        if (strcmp(h->name, name) == 0) return h->value;
        h++;
    }
    return NULL;
}

void handle(int newsock)
{
    //static int count = 0;
    /* recv(), send(), close() */
    int rcvd;

    buf = malloc(65535);
    rcvd=recv(newsock, buf, 65535, 0);

    if (rcvd<0)    // receive error
        fprintf(stderr,("recv() error\n"));
    else if (rcvd==0)    // receive socket closed
        fprintf(stderr,"Client disconnected unexpectedly.\n");
    else    // message received
    {
        buf[rcvd] = '\0';

        //fputs(buf, stdout);
        //fprintf(stdout, "count = %d\n", count);

        method = strtok(buf,  " \t\r\n");
        uri    = strtok(NULL, " \t");
        prot   = strtok(NULL, " \t\r\n"); 

        fprintf(stderr, "\x1b[32m + [%s] %s\x1b[0m\n", method, uri);

        if ((qs = strchr(uri, '?')))
        {
            *qs++ = '\0'; //split URI
        } else {
            qs = uri - 1; //use an empty string
        }

        header_t *h = reqhdr;
        char *t = (char *)reqhdr;
        char *t2;
        while(h < reqhdr+16) {
            char *k,*v;
            k = strtok(NULL, "\r\n: \t");
            if (!k)
                break;
            v = strtok(NULL, "\r\n");
            while(*v && *v==' ')
                v++;
            h->name  = k;
            h->value = v;
            h++;
            fprintf(stderr, "[H] %s: %s\n", k, v);
            t = v + 1 + strlen(v);
            if (t[1] == '\r' && t[2] == '\n')
                break;
        }
        t+=2;
        t++; // now the *t shall be the beginning of user payload
        t2 = request_header("content-length"); // and the related header if there is  
        payload = t;
        payload_size = t2 ? atol(t2) : (rcvd-(t-buf));

        fprintf(stdout, "-- payload len = %d >", payload_size);
        fputs(payload, stdout);
        fprintf(stdout, "<\r\n");

        if (strcmp(method, "GET") == 0)
        {
            fprintf(stdout, "\nit's a GET!\r\n");
        }
        else if (strcmp(method, "POST") == 0)
        {
            fprintf(stdout, "\nit's a POST!\r\n");   
        }

        sprintf(buf, "HTTP/1.1 200 OK\r\n\r\n");
        send(newsock, buf, strlen(buf), 0);
        close(newsock);
        free(buf);
    }
}

int HTTPSERVER_init(const char *tcpport)
{
    int sock;
    struct addrinfo hints, *res;
    int reuseaddr = 1; /* True */
    sigset_t sigset, oldset;

    sigfillset(&sigset);
    pthread_sigmask(SIG_BLOCK, &sigset, &oldset);

    /* Get the address info */
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    if (getaddrinfo(NULL, tcpport, &hints, &res) != 0) {
        perror("getaddrinfo");
        return 1;
    }

    /* Create the socket */
    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (sock == -1) {
        perror("socket");
        return 1;
    }

    /* Enable the socket to reuse the address */
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1) {
        perror("setsockopt");
        return 1;
    }

    /* Bind to the address */
    if (bind(sock, res->ai_addr, res->ai_addrlen) == -1) {
        perror("bind");
        return 1;
    }

    /* Listen */
    if (listen(sock, BACKLOG) == -1) {
        perror("listen");
        return 1;
    }

    freeaddrinfo(res);

    /* Main loop */
    while (1) {

        printf("waiting on accept\n");
        fflush(stdout);

        socklen_t size = sizeof(struct sockaddr_in);
        struct sockaddr_in their_addr;
        int newsock = accept(sock, (struct sockaddr*)&their_addr, &size);

        if (newsock == -1) {
            perror("accept");
        }
        else {
            printf("Got a connection from %s on port %d\n", 
                    inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port));
            handle(newsock);
        }
    }

    close(sock);

    return 0;
}

@eyllanesc指出,待处理的字符串“每秒的世界你好!\ r \ n”几秒钟后最终出现。

moduleThread应该是线程,而不是不同的进程:这由commadn“ ps aux”验证,其中仅显示“ ../program/testApp test 32001”。

请问您有什么建议吗?

感谢您的时间,

弗朗切斯科

0 个答案:

没有答案