I'm trying to communicate with a device which provided a serial port. When I use the example C program provided by the device producer, it was successfully connected and I can send/receive data. But when I use my C++ program with QSerialPort, the open() method returned false and the error() returned 11 (An unidentified error occurred, as described by Qt documentation). Could anyone please help me?
OS: Cent OS 6.9
gcc/g++: 4.8
Qt: 5.6.0
An example of connecting with QSerialPort:
#include <qserialport.h>
#include <qstring.h>
int main(int argc, const char *argv[])
{
QString portName = "/dev/corser/x64ExpCL4x1_s0";
QSerialPort *pSerial = new QSerialPort();
pSerial->setPortName(portName);
pSerial->setBaudRate(QSerialPort::Baud9600);
pSerial->setParity(QSerialPort::NoParity);
pSerial->setDataBits(QSerialPort::Data8);
pSerial->setStopBits(QSerialPort::OneStop);
pSerial->setFlowControl(QSerialPort::NoFlowControl);
bool success = pSerial->open(QIODevice::ReadWrite);
if (!success) {
printf("Error: %d\n", pSerial->error());
} else {
printf("Success.\n");
pSerial->close();
}
delete pSerial;
return 0;
}
This program prints out Error: 11.
Here is a C program which is excerpted from the device's example program. This program just try to connect the serial port and then close the connection. While the original example program is complicated. It is actually kind of a "Terminal" program which sends user-input commands to the device and prints out the responses from the device.
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <ctype.h> /* Character types */
#define TRUE 1
#define FALSE 0
typedef struct
{
int open; // Flag for current open status of port
int update; // Flag indicating parameter changes
char *port; // Current port to be opened
int iod; // I/O index for open device port
struct termios stty; // Terminal port control structure
} SCOM_CTL;
struct termios ttctl = {0};
struct termios ttsav = {0};
struct termios coctl = {0};
struct termios cnctl = {0};
#define OPEN 1
#define CLOSE 2
#define UPDATE 3
#define NO_UPDATE 4
SCOM_CTL scom;
int main( int argc, char **argv )
{
scom.port = "/dev/corser/x64ExpCL4x1_s0";
scom_init();
scom_open_port();
if (scom.open == OPEN)
{
fputs("\rSuccess.\r\n", stdout);
scom_close_port(scom.iod);
}
else
{
fputs("\rError.\r\n", stdout);
}
}
// Initialize the console (stdin) for raw access.
int scom_init()
{
int i;
scom.open = CLOSE;
scom.update = NO_UPDATE;
scom.iod = -1;
tcgetattr(0, &coctl); // Save a copy to restore stdin.
tcgetattr(0, &cnctl);
cfmakeraw( &cnctl); // Set stdin to raw !
tcsetattr(0, 0, &cnctl);
}
int scom_open_port()
{
int i, iod;
if (scom.open == OPEN)
{
close(scom.iod);
scom.open = CLOSE;
}
if ( (iod = open( scom.port, (O_RDWR | O_NOCTTY))) == -1)
{
conres(); /* Reset the console. */
fputs("term : Open Failure on device\n", stdout);
return -1;
}
scom.iod = iod;
scom.open = OPEN;
scom.update = NO_UPDATE;
}
int scom_close_port()
{
scom.open = CLOSE;
close(scom.iod);
}
int conres()
{
return(tcsetattr(0, 0, &coctl));
}
This program prints out Success.
I have a C++ program that uses R API to send commands to R and display the result. Once reduced to it's minimal form, it's an R console coded in C++.
It used to work fine (most of the time) with R.3.4.3 and R.3.4.4, but everything falls appart when I tried to make the transition to R.3.5.1.
For some commands (typically a call to "par", or "barplot", or anything related to graphics), I get the error message: "Error in < My command > : the base graphics system is not registered"
I never encountered this error before, and google searching it gives surprisingly few results.
My console using R3.4.3 (it's the same with 3.4.4) :
The same commands using R3.5.1:
Note that this behavior does not happen in a regular R console, so it must have something to do with the R-API for C/C++ (and the way it handles graphics devices, maybe?).
My code consists essentially in a RManager class that calls the API to exchange with R, and a simple window providing a lineEdit where user can input its command, and a text field where R results are displayed (see images above).
I'll provide the full code for reproducibility, but if you want to jump where R communication is really handled, it all happens in rmanager.cpp, the rest is just the GUI.
main.cpp:
#include "mainwindow.h"
#include <QApplication>
#include <thread>
#include <iostream>
#include <chrono>
#ifdef _WIN32
#include <windows.h>
#include <tlhelp32.h>
#include <QProcess>
#include <cwchar>
#endif
int main(int argc, char *argv[])
{
int result = 0;
QApplication a(argc, argv);
MainWindow w;
w.show();
result = a.exec();
return result;
}
MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTextStream>
#include <QFile>
#include <QTimer>
#include <rmanager.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
// Command received from GUI
void on_inputCmd_returnPressed();
// Read result from the R Manager
void getResult(QString);
//Read errors from the R Manager
void getError(QString);
private:
Ui::MainWindow *ui;
QTimer pollInput;
RManager *rconsole;
// Result buffer for last command
QString resultBuffer;
// Send command directly to R
void sendRCmd(QString command);
signals:
// Starts the R Manager event loop
void runConsole();
};
#endif // MAINWINDOW_H
mainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this); // Just a QLineEdit for inputs and a QTextEdit to display result.
ui->outputConsole->document()->setMaximumBlockCount(500);
// R API connection
rconsole = new RManager(parent);
// Signals connection
connect(rconsole, SIGNAL(writeConsole(QString)), this, SLOT(getResult(QString)));
connect(rconsole, SIGNAL(writeConsoleError(QString)), this, SLOT(getError(QString)));
connect(this, SIGNAL(runConsole()), rconsole, SLOT(runConsole()));
pollInput.start(10); // Check for R results every 10 ms.
// R Callbacks event loop
emit runConsole();
}
MainWindow::~MainWindow()
{
delete ui;
pollInput.stop();
}
/**
* #brief MainWindow::getResult Aggregate results from R until an only '\n' is sent
* Then send it to the user (RPP or GUI)
* #param res
*/
void MainWindow::getResult(QString res)
{
// While != "\n" add res to the result buffer
if (res != "\n") {
resultBuffer.append(res);
} else {
// the res to the resultBuffer to conserve the last \n
resultBuffer.append(res);
// Get the current text values from the text fields and append the result
ui->outputConsole->append(resultBuffer);
resultBuffer.clear();
}
}
/**
* #brief MainWindow::getError Send immediatly any error from R
* #param error
*/
void MainWindow::getError(QString error)
{
qDebug() << "getError called with error: " << error ;
// Get the current text values from the text fields and append the result
ui->outputConsole->append(error);
}
/**
* #brief MainWindow::sendRCmd Low level method to send command to R
* Display the command in the GUI
* #param command
*/
void MainWindow::sendRCmd(QString command)
{
ui->outputConsole->append("> "+command+"\n");
// Send the command to R
rconsole->parseEval(command);
ui->inputCmd->clear();
}
/**
* #brief MainWindow::on_inputCmd_returnPressed Send command to R from the GUI
*/
void MainWindow::on_inputCmd_returnPressed()
{
// Get the current text values from the text fields
QString command = ui->inputCmd->text();
sendRCmd(command);
}
ui_mainwindow.h (generated by Qt Creator):
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.11.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QTextEdit>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QWidget *centralWidget;
QVBoxLayout *verticalLayout;
QTextEdit *outputConsole;
QLineEdit *inputCmd;
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QStringLiteral("MainWindow"));
MainWindow->resize(382, 413);
centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
verticalLayout = new QVBoxLayout(centralWidget);
verticalLayout->setSpacing(6);
verticalLayout->setContentsMargins(11, 11, 11, 11);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
outputConsole = new QTextEdit(centralWidget);
outputConsole->setObjectName(QStringLiteral("outputConsole"));
outputConsole->setFocusPolicy(Qt::NoFocus);
outputConsole->setUndoRedoEnabled(false);
outputConsole->setReadOnly(true);
verticalLayout->addWidget(outputConsole);
inputCmd = new QLineEdit(centralWidget);
inputCmd->setObjectName(QStringLiteral("inputCmd"));
inputCmd->setClearButtonEnabled(true);
verticalLayout->addWidget(inputCmd);
MainWindow->setCentralWidget(centralWidget);
retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAINWINDOW_H
rmanager.h
#ifndef RMANAGER_H
#define RMANAGER_H
#include <QObject>
class RManager : public QObject
{
Q_OBJECT
public:
explicit RManager(QObject *parent = 0);
// R side methods/callbacks
int parseEval(const QString & line);
// R interface callbacks
void myShowMessage( const char* message );
void myWriteConsoleEx( const char* message, int len, int oType );
int myReadConsole(const char *, unsigned char *, int, int);
int winReadConsole(const char*, char*, int, int);
void myResetConsole();
void myFlushConsole();
void myCleanerrConsole();
void myBusy( int which );
static RManager &r();
signals:
void writeConsole(QString);
void writeConsoleError(QString);
public slots:
void runConsole();
private:
bool R_is_busy;
static RManager *r_inst;
};
// Functions to match the library : call RManager's methods
void myR_ShowMessage( const char* message );
void myR_WriteConsoleEx( const char* message, int len, int oType );
int myR_ReadConsole(const char *prompt, unsigned char *buf, int len, int addtohistory);
int ReadConsole(const char *prompt, char *buf, int len, int addtohistory);
void myR_ResetConsole();
void myR_FlushConsole();
void myR_ClearerrConsole();
void myR_Busy( int which );
void myR_CallBack();
void myR_AskOk(const char *);
int myR_AskYesNoCancel(const char *);
#endif // RMANAGER_H
And finally, rmanager.cpp
#include "rmanager.h"
#include <qmessagebox.h>
#include <QDebug>
#define R_INTERFACE_PTRS
#include <Rembedded.h>
#ifndef _WIN32
#include <Rinterface.h> // For Linux.
#endif
#include <R_ext/RStartup.h>
#include <Rinternals.h>
#include <R_ext/Parse.h>
#include <locale.h>
RManager* RManager::r_inst = 0 ;
RManager::RManager(QObject *parent) : QObject(parent)
{
if (r_inst) {
throw std::runtime_error( tr("Il ne peut y avoir qu'une instance de RppConsole").toStdString() ) ;
} else {
r_inst = this ;
}
const char *argv[] = {"RConsole", "--gui=none", "--no-save",
"--silent", "--vanilla", "--slave"};
int argc = sizeof(argv) / sizeof(argv[0]);
setlocale(LC_NUMERIC, "C"); //try to ensure R uses .
#ifndef _WIN32
R_SignalHandlers = 0; // Don't let R set up its own signal handlers
#endif
Rf_initEmbeddedR(argc, (char**)argv); // The call that is supposed to register the graphics system, amongst other things.
R_ReplDLLinit(); // this is to populate the repl console buffers
structRstart Rst;
R_DefParams(&Rst);
Rst.R_Interactive = (Rboolean) false; // sets interactive() to eval to false
#ifdef _WIN32
Rst.rhome = getenv("R_HOME");
Rst.home = getRUser();
Rst.CharacterMode = LinkDLL;
Rst.ReadConsole = ReadConsole;
Rst.WriteConsole = NULL;
Rst.WriteConsoleEx = myR_WriteConsoleEx;
Rst.CallBack = myR_CallBack;
Rst.ShowMessage = myR_AskOk;
Rst.YesNoCancel = myR_AskYesNoCancel;
Rst.Busy = myR_Busy;
#endif
R_SetParams(&Rst);
// Assign callbacks to R's
#ifndef _WIN32
ptr_R_ShowMessage = myR_ShowMessage ;
ptr_R_ReadConsole = myR_ReadConsole;
ptr_R_WriteConsoleEx = myR_WriteConsoleEx ;
ptr_R_WriteConsole = NULL;
ptr_R_ResetConsole = myR_ResetConsole;
ptr_R_FlushConsole = myR_FlushConsole;
ptr_R_ClearerrConsole = myR_ClearerrConsole;
ptr_R_Busy = myR_Busy;
R_Outputfile = NULL;
R_Consolefile = NULL;
#endif
#ifdef TIME_DEBUG
_earliestSendToRBool = false;
#endif
Rf_endEmbeddedR(0);
}
RManager &RManager::r()
{
return *r_inst;
}
void RManager::runConsole()
{
// Start the event loop to get results from R
R_ReplDLLinit();
while (R_ReplDLLdo1() > 0) {}
}
/**
* #brief RManager::parseEval is the core of this console, sending commands to R.
* #param line
* #return
*/
int RManager::parseEval(const QString &line) {
ParseStatus status;
SEXP cmdSexp, cmdexpr = R_NilValue;
int i, errorOccurred, retVal=0;
// Convert the command line to SEXP
PROTECT(cmdSexp = Rf_allocVector(STRSXP, 1));
SET_STRING_ELT(cmdSexp, 0, Rf_mkChar(line.toLocal8Bit().data()));
cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, &status, R_NilValue));
switch (status){
case PARSE_OK:
// Loop is needed here as EXPSEXP might be of length > 1
for(i = 0; ((i < Rf_length(cmdexpr)) && (retVal==0)); i++){
R_tryEval(VECTOR_ELT(cmdexpr, i), R_GlobalEnv, &errorOccurred);
if (errorOccurred) {
retVal = -1;
}
}
break;
case PARSE_INCOMPLETE:
// need to read another line
retVal = 1;
break;
case PARSE_NULL:
Rf_warning(tr("%s: Etat d'analyse de commande : NULL (%d)\n").toStdString().data(), "RPPConsole", status);
retVal = -2;
break;
case PARSE_ERROR:
Rf_warning(tr("Erreur d'analyse de la commande : \"%s\"\n").toStdString().data(), line.toStdString().c_str());
retVal = -2;
break;
case PARSE_EOF:
Rf_warning(tr("%s: Etat d'analyse de commande : EOF (%d)\n").toStdString().data(), "RPPConsole", status);
break;
default:
Rf_warning(tr("%s: Etat d'analyse de commande non documenté %d\n").toStdString().data(), "RPPConsole", status);
retVal = -2;
break;
}
UNPROTECT(2);
return retVal;
}
// RManager callbacks implementation
void RManager::myShowMessage(const char *message)
{
// Never called till now
QMessageBox::information(qobject_cast<QWidget*>(parent()),QString(tr("Bonjour le monde")),QString(message),QMessageBox::Ok,QMessageBox::NoButton);
}
void RManager::myWriteConsoleEx(const char *message, int len, int oType)
{
QString msg;
if (len) {
msg = QString::fromLocal8Bit(message, len);
if(!oType)
emit writeConsole(msg);
else
emit writeConsoleError(msg);
}
}
int RManager::myReadConsole(const char* /*prompt*/, unsigned char* /*buf*/, int /*len*/, int /*addtohistory*/ ){
return 0;
}
// For Windows, unsigned char is replaced by char
int RManager::winReadConsole(const char* /*prompt*/, char* /*buf*/, int /*len*/, int /*addtohistory*/ ){
return 0;
}
void RManager::myResetConsole()
{
}
void RManager::myFlushConsole()
{
}
void RManager::myCleanerrConsole()
{
}
void RManager::myBusy( int which ){
R_is_busy = static_cast<bool>( which ) ;
}
// Connects R callbacks to RManager static methods
void myR_ShowMessage( const char* message ){
RManager::r().myShowMessage( message ) ;
}
void myR_WriteConsoleEx( const char* message, int len, int oType ){
RManager::r().myWriteConsoleEx(message, len, oType);
}
int myR_ReadConsole(const char *prompt, unsigned char *buf, int len, int addtohistory){
return RManager::r().myReadConsole( prompt, buf, len, addtohistory ) ;
}
int ReadConsole(const char *prompt, char *buf, int len, int addtohistory) {
return RManager::r().winReadConsole( prompt, buf, len, addtohistory ) ;
}
void myR_ResetConsole(){
RManager::r().myResetConsole();
}
void myR_FlushConsole(){
RManager::r().myFlushConsole();
}
void myR_ClearerrConsole(){
RManager::r().myCleanerrConsole();
}
void myR_Busy( int which ){
RManager::r().myBusy(which);
}
void myR_CallBack() {
// Called during i/o, eval, graphics in ProcessEvents
}
void myR_AskOk(const char* /*info*/) {
}
int myR_AskYesNoCancel(const char* /*question*/) {
const int yes = 1;
return yes;
}
Thank you in advance for your ideas on what the problem might be. Is it a R.3.5.1 bug, or is there something that I should have defined/connected and missed ? I read the R.3.5.1 changes description without finding a clue about it.
PS: I'm under windows 10, compiling with Microsoft Visual C++ Compiler 15.0 (32 bits), and using Qt 5.11.0 (for the GUI components).
PPS: Following user2554330's advice, I checked for calls to GEregisterSystem, that is supposed to set the graphics system, and thus prevent this error. I found that in both cases, this function is called, at application launch, but not with the same call stack.
For R.3.4.3:
For R.3.5.1:
I found a solution (thanks to Luke Tierney on R-devel mailing list).
I just needed to move the call to Rf_endEmbeddedR to the destructor of RManager, where it should have been.
It doesn't really explain why it worked the way it was before with R.3.4 and not with R.3.5, but it does solve the practical issue.
Maybe this was never supposed to work with Rf_endEmbeddedR called so soon, and it only used to, thanks to a bug that has been fixed.
How to disable buffering in pipe. I'm creating a simple recorder/player for I/O. To do this I need record output witch time delays.
To record delays, I need something like this
example tekst
"wait 1s"
example tekst
"wait 1s"
example tekst
...
but if I use
pipe2(in, O_DIRECT );
i see something like this
"wait 100s"
"100 times" example tekst
"wait 100s"
"100 times" example tekst
...
man7 tells:
O_DIRECT (since Linux 3.4)
Create a pipe that performs I/O in "packet" mode. Each
write(2) to the pipe is dealt with as a separate packet, and
read(2)s from the pipe will read one packet at a time.
I tried to disable buffering, by:
fcntl(in[1], F_SETPIPE_SZ, 1);
but it's still not working.
read.cpp
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <assert.h>
bool keep = true;
void intHandler(int dummy) {
keep = 0;
}
int main(void) {
signal(SIGINT, intHandler);
int in[2];
int out[2];
int pid;
int fo;
char buf[1024];
pipe2(in, O_DIRECT );
pipe2(out, O_DIRECT );
pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
close(in[0]);
close(out[1]);
close(0);
close(1);
dup2(in[1], 1);
dup2(out[0], 0);
close(in[1]);
close(out[0]);
sleep(1);
char *newargv[] = {"/root/Pulpit/a1", NULL, NULL, NULL};
char *newenviron[] = {NULL};
int ret = execve("/root/Pulpit/a1", newargv, newenviron);
printf("%d", ret);
return 0;
} else {
close(out[0]);
close(in[1]);
int n = 0;
while (keep) {
int wyn = read(in[0], buf, 1024);
if (wyn > 0) {
char aa[1024];
write(1, buf, wyn);
fsync(1);
}
}
}
return (0);
}
a1.cpp
#include <cstdlib>
#include <unistd.h>
#include "stdio.h"
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
while(true){
printf("example text\n");
usleep(100000);
}
return 0;
}
I am trying to write a program that has two separate process that talk via named pipes. The client which sends a message to a server, and the server which needs to broadcast that message to all clients attached to it. So far, I can get a connection between the two, but I cannot get more than one message to work no matter what I have tried. Below is the code I have written that will allow a connection and transmission of a single message.
server.cpp:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#define FIFO_FILE_1 "/tmp/client_to_server_fifo"
#define FIFO_FILE_2 "/tmp/server_to_client_fifo"
int main()
{
int client_to_server;
int server_to_client;
char buf[BUFSIZ];
/* create the FIFO (named pipe) */
mkfifo(FIFO_FILE_1, 0666);
mkfifo(FIFO_FILE_2, 0666);
printf("Server ON.\n");
while (1)
{
/* open, read, and display the message from the FIFO */
client_to_server = open(FIFO_FILE_1, O_RDONLY);
server_to_client = open(FIFO_FILE_2, O_WRONLY);
read(client_to_server, buf, BUFSIZ);
if (strcmp("exit",buf)==0)
{
printf("Server OFF.\n");
break;
}
else if (strcmp("",buf)!=0)
{
printf("Received: %s\n", buf);
printf("Sending back...\n");
write(server_to_client,buf,BUFSIZ);
}
/* clean buf from any data */
memset(buf, 0, sizeof(buf));
close(client_to_server);
close(server_to_client);
}
close(client_to_server);
close(server_to_client);
unlink(FIFO_FILE_1);
unlink(FIFO_FILE_2);
return 0;
}
client.cpp:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>
#include <string.h>
#define FIFO_FILE_1 "/tmp/client_to_server_fifo"
#define FIFO_FILE_2 "/tmp/server_to_client_fifo"
int main()
{
system("clear");
int client_to_server;
int server_to_client;
char str[140];
printf("Input message to server: ");
scanf("%139[^\r\n]", str);
/* write str to the FIFO */
client_to_server = open(FIFO_FILE_1, O_WRONLY);
server_to_client = open(FIFO_FILE_2, O_RDONLY);
if(write(client_to_server, str, sizeof(str)) < 0){
perror("Write:");//print error
exit(-1);
}
if(read(server_to_client,str,sizeof(str)) < 0){
perror("Read:"); //error check
exit(-1);
}
printf("\n...received from the server: %s\n\n\n",str);
close(client_to_server);
close(server_to_client);
/* remove the FIFO */
return 0;
}
close(client_to_server);
close(server_to_client);
Remove these lines from while loop because when server has done its work for the first time it will close the pipe and you cant be able to proceed further in pipes.
So, I'm trying to follow the tutorial given
http://qt-project.org/doc/qt-5/unix-signals.html
to catch UNIX/Linux signals and do something Qt related when triggered by them.
It's on the qtDocs, so I consider it legit.
My present code is as follows:
mydaemon.cpp
#include "mydaemon.h"
#include <QDebug>
#include <QObject>
#include <QSocketNotifier>
#include <csignal>
#include <sys/socket.h>
#include <iostream>
#include <stdio.h>
#include <signal.h>
//needed to not get an undefined reference to static members
int MyDaemon::sighupFd[2];
int MyDaemon::sigtermFd[2];
MyDaemon::MyDaemon(QObject *parent)
: QObject(parent)
{
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sighupFd))
qFatal("Couldn't create HUP socketpair");
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermFd))
qFatal("Couldn't create TERM socketpair");
snHup = new QSocketNotifier(sighupFd[1], QSocketNotifier::Read, this);
connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup()));
snTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this);
connect(snTerm, SIGNAL(activated(int)), this, SLOT(handleSigTerm()));
}
MyDaemon::~MyDaemon() {}
void MyDaemon::hupSignalHandler(int)
{
qDebug() << "signal hup";
char a = '1';
::write(sighupFd[0], &a, sizeof(a));
}
void MyDaemon::termSignalHandler(int)
{
qDebug() << "signal term";
char a = '1';
::write(sigtermFd[0], &a, sizeof(a));
}
void MyDaemon::handleSigTerm()
{
snTerm->setEnabled(false);
char tmp;
::read(sigtermFd[1], &tmp, sizeof(tmp));
// do Qt stuff
qDebug() << "MyDaemon::handleSigTerm";
snTerm->setEnabled(true);
}
void MyDaemon::handleSigHup()
{
snHup->setEnabled(false);
char tmp;
::read(sighupFd[1], &tmp, sizeof(tmp));
// do Qt stuff
qDebug() << "MyDaemon::handleSigHup";
snHup->setEnabled(true);
}
Now, when I create my C++ class, and try to build, it gives the errors such as,
/home/xxxx/Documents/Qt Projects/mainScreen/mydaemon.cpp:-1: In static member function 'static void MyDaemon::termSignalHandler(int)':
/home/xxxx/Documents/Qt Projects/mainScreen/mydaemon.cpp:49: error: '::write' has not been declared
::write(sigtermFd[0], &a, sizeof(a));
^
and so on, for all instances of the ::read() or ::write() calls. I'm not sure what I'm doing wrong, I'm grateful for any help :)
If you are using "basic" Unix functions, you need to use
#include <unistd.h>
This will give you read, write, open, close, sleep, usleep and many other functions.