Моя платформа:
- Ubuntu 17.10 32-bit (Vbox VM)
- Qt Creator 3.5.1 (с открытым исходным кодом)
- Qt 5.5.1 (GCC4.9.1 20140922 (Red Hat 4.9.1-10), 32-битная
Я пытаюсь вызвать многопоточную программу (с аргументами), используя QProcess .start ().
Моя программа работает нормально на терминале, то есть периодически печатает на стандартный вывод.
Использование TextEdit для записи stdout / stderr программы, которую я подключил QProcess readyReadStandardOutput / Ошибка сигналов.
Stdout / stderr, который поступает из основного потока программы, правильно отображается в TextEdit, остальная часть вывода (один из всех других потоков) не
EDIT
В основном потоке прослушивает HTTP-сервер.
Если HTTP-запрос выполняется браузером по URL-адресу "127.0.0.1: 32001 "(порт 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, ожидающие строки "Hello world каждую секунду! \ R \ n" в конечном итоге выходят через несколько секунд.
ModuleThread должен быть потоком, а не другим процессом: это проверено commadn "ps aux", который показывает только "../program/testApp test 32001".
Может ли кто-нибудь из вас любезно дать мненамекните, что здесь происходит, пожалуйста?
Спасибо за ваше время,
Франческо