After several days of searching it's time to ask. Environment is Ubuntu 12.04/Gnome.
I'm developing some embedded code on the ubuntu box and testing as much as I can in that environment before porting over to the embedded processor. The current routine is a real time fast fourier transform and I want to use gnuplot to display the results. So I want my test code AND gnuplot to run in the foreground at the same time and communicate via a pipe.
I did the usual popen() call and that worked except for one thing. stdin for the child (gnuplot) is still attached to the console. It is in contention with the parent process. The parent process needs to receive keystrokes to modify its behaviour. Sometimes the parent gets the keystroke and sometimes gnuplot does.
So I've tried the fork/exec path. Specifically
pid_t pg = tcgetpgrp(1); // get process group associated with stdout
cerr << "pid_t pg = " << pg << endl;
cerr << "process pid is " << getpid() << endl;
if (pipe(pipefd) == -1) {// open the pipe
cerr << "pipe failure" << endl;
exit(3);
} // if pipe
cpid = fork();
if (cpid == -1) {
cerr << "fork failure" << endl;
exit(1);
}
if (cpid == 0) { // this is the child process
if (tcsetpgrp(1, pg) == -1) { // this should set the process associated with stdin (gnuplot) with the
cerr << "tcsetgrp failed" << endl; // foreground terminal.
exit(7);
}
close(pipefd[1]); // close child's writing handle
if (pipefd[0] != STDIN_FILENO) { // this changes the file descripter of stdin back to 0
if ( dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
cerr << "dup2 error on stdin" << endl;
exit(6);
}
}
if (execl("/usr/bin/gnuplot", "gnuplot", "-background", "white", "-raise", (char *) NULL)) {
cerr << "execl failed" << endl;
exit(2);
} else // if exec
close(pipefd[0]); // close parent's reading handle
} // if cpid
// back in parent process
This fires off gnuplot as I expect it should. I can see gnuplot consuming all the resources of one core as it normally does. The problem is that no graph appears on the screen.
So my question is, how do I start a child process, totally detach it from the console so it won't get any keystrokes and get the output of gnuplot to display?
Related
My aim is to enable communication via USB CDC HS on STM32 with Ubuntu 20.04 based PC in Qt app created in QtCreator.
So far I've managed to run communication via UART and everything is working fine. Then I decided to switch to USB and I still can read incoming data (but only in CuteCom) and in my Qt app nothing appears.
To be honest I have no idea what is going on and where to look for mistakes. Here I put the code:
void MainWindow::on_pushButtonConnect_clicked()
{
if (ui->comboBoxDevices->count() == 0){
this->addToLogs("No devices found.");
return;
}
QString portName = ui->comboBoxDevices->currentText().split(" ").first();
this->device->setPortName(portName);
this->device->setBaudRate(QSerialPort::Baud115200);
this->device->setDataBits(QSerialPort::Data8);
this->device->setParity(QSerialPort::NoParity);
this->device->setStopBits(QSerialPort::OneStop);
this->device->setFlowControl(QSerialPort::NoFlowControl);
if(device->open(QIODevice::ReadWrite)){
this->addToLogs("Port opened. Setting the connection params...");
this->addToLogs("UART enabled.");
qDebug() << "Writing down the parameters...";
qDebug() << "Baud rate:" << this->device->baudRate();
qDebug() << "Data bits:" << this->device->dataBits();
qDebug() << "Stop bits:" << this->device->stopBits();
qDebug() << "Parity:" << this->device->parity();
qDebug() << "Flow control:" << this->device->flowControl();
qDebug() << "Read buffer size:" << this->device->readBufferSize();
qDebug() << "Read buffer size:" << this->device->portName();
connect(this->device, SIGNAL(readyRead()), this, SLOT(readFromPort()));
} else {
this->addToLogs("The port can not be opened.");
}
And the readFromPort() function:
void MainWindow::readFromPort()
{
while(this->device->canReadLine()){
QString line = this->device->readLine();
qDebug() << line;
QString terminator = "\r";
int pos = line.lastIndexOf(terminator);
qDebug()<<line.left(pos);
this->addToLogs(line.left(pos));
}
}
Do you have any idea what might be wrong or not set properly? Would be thankful for all help.
As it seems, in my code I put commands to read the port in if (with function canReadLine()). When I commented the whole condition out leaving just the reading, everything worked fine.
While studying the possibility of improving Recoll performance by using vfork() instead of fork(), I've encountered a fork() issue which I can't explain.
Recoll repeatedly execs external commands to translate files, so that's what the sample program does: it starts threads which repeatedly execute "ls" and read back the output.
The following problem is not a "real" one, in the sense that an actual program would not do what triggers the issue. I just stumbled on it while having a look at what threads were stopped or not between fork()/vfork() and exec().
When I have one of the threads busy-looping between fork() and exec(), the other thread never completes the data reading: the last read(), which should indicate eof, is blocked forever or until the other thread's looping ends (at which point everything resumes normally, which you can see by replacing the infinite loop with one which completes). While read() is blocked, the "ls" command has exited (ps shows <defunct>, a zombie).
There is a random aspect to the issue, but the sample program "succeeds" most of the time. I tested with Linux kernels 3.2.0 (Debian), 3.13.0 (Ubuntu) and 3.19 (Ubuntu). Works on a VM, but you need at least 2 procs, I could not make it work with one processor.
Here follows the sample program, I can't see what I'm doing wrong.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <memory.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
#include <iostream>
using namespace std;
struct thread_arg {
int tnum;
int loopcount;
const char *cmd;
};
void* task(void *rarg)
{
struct thread_arg *arg = (struct thread_arg *)rarg;
const char *cmd = arg->cmd;
for (int i = 0; i < arg->loopcount; i++) {
pid_t pid;
int pipefd[2];
if (pipe(pipefd)) {
perror("pipe");
exit(1);
}
pid = fork();
if (pid) {
cerr << "Thread " << arg->tnum << " parent " << endl;
if (pid < 0) {
perror("fork");
exit(1);
}
} else {
// Child code. Either exec ls or loop (thread 1)
if (arg->tnum == 1) {
cerr << "Thread " << arg->tnum << " looping" <<endl;
for (;;);
//for (int cc = 0; cc < 1000 * 1000 * 1000; cc++);
} else {
cerr << "Thread " << arg->tnum << " child" <<endl;
}
close(pipefd[0]);
if (pipefd[1] != 1) {
dup2(pipefd[1], 1);
close(pipefd[1]);
}
cerr << "Thread " << arg->tnum << " child calling exec" <<
endl;
execlp(cmd, cmd, NULL);
perror("execlp");
_exit(255);
}
// Parent closes write side of pipe
close(pipefd[1]);
int ntot = 0, nread;
char buf[1000];
while ((nread = read(pipefd[0], buf, 1000)) > 0) {
ntot += nread;
cerr << "Thread " << arg->tnum << " nread " << nread << endl;
}
cerr << "Total " << ntot << endl;
close(pipefd[0]);
int status;
cerr << "Thread " << arg->tnum << " waiting for process " << pid
<< endl;
if (waitpid(pid, &status, 0) != -1) {
if (status) {
cerr << "Child exited with status " << status << endl;
}
} else {
perror("waitpid");
}
}
return 0;
}
int main(int, char **)
{
int loopcount = 5;
const char *cmd = "ls";
cerr << "cmd [" << cmd << "]" << " loopcount " << loopcount << endl;
const int nthreads = 2;
pthread_t threads[nthreads];
for (int i = 0; i < nthreads; i++) {
struct thread_arg *arg = new struct thread_arg;
arg->tnum = i;
arg->loopcount = loopcount;
arg->cmd = cmd;
int err;
if ((err = pthread_create(&threads[i], 0, task, arg))) {
cerr << "pthread_create failed, err " << err << endl;
exit(1);
}
}
void *status;
for (int i = 0; i < nthreads; i++) {
pthread_join(threads[i], &status);
if (status) {
cerr << "pthread_join: " << status << endl;
exit(1);
}
}
}
What's happening is that your pipes are getting inherited by both child processes instead of just one.
What you want to do is:
Create pipe with 2 ends
fork(), child inherits both ends of the pipe
child closes the read end, parent closes the write end
...so that the child ends up with just one end of one pipe, which is dup2()'ed to stdout.
But your threads race with each other, so what can happen is this:
Thread 1 creates pipe with 2 ends
Thread 0 creates pipe with 2 ends
Thread 1 fork()s. The child process has inherited 4 file descriptors, not 2!
Thread 1's child closes the read end of the pipe that thread 1 opened, but it keeps a reference to the read end and write end of thread 0's pipe too.
Later, thread 0 waits forever because it never gets an EOF on the pipe it is reading because the write end of that pipe is still held open by thread 1's child.
You will need to define a critical section that starts before pipe(), encloses the fork(), and ends after close() in the parent, and enter that critical section from only one thread at a time using a mutex.
My son is implementing a server on a Raspberry Pi that allows control of the GPIO pins via a network connection. He has discovered some strange behaviour, which at first seemed like a bug (but see answer below).
First, the OS being used is Raspbian, a version of Debian Linux. He is using the standard system file to control the GPIO ports.
We start with a GPIO pin, e.g. pin 17, in a non-exported state. For example,
echo "17" > /sys/class/gpio/unexport
Now, if the server is asked to turn on pin 17, it does the following:
Opens the /sys/class/gpio/export, writes "17" to it, and closes the export file
Open the /sys/class/gpio/gpio17/direction file for read, examines it to see if it is set as input or output. Closes the file. Then, if necessary, re-opens the file for write and writes "out" to the file, to set the pin as an output pin, and closes the direction file.
At this point, we should be able to open /sys/class/gpio/gpio17/value for write, and write a "1" to it.
However, the permissions on the /sys/class/gpio/gpio17/value file exists but the group permissions is read-only. If we put in a "sleep" in order to wait for a fraction of a second, the permissions change so the group permission has write permissions.
I would have expected that the OS should not return from the write to the direction file until it had set the permissions on the value file correctly.
Why is this happening? It seems like a bug. Where should I report this (with more detail...)? See answer below.
What follows are the relevant bits of code. The code has been edited and paraphrased a bit, but it is essentially what is being used. (Keep in mind it's the code of a grade 12 student trying to learn C++ and Unix concepts):
class GpioFileOut
{
private:
const string m_fName;
fstream m_fs;
public:
GpioFileOut(const string& sName)
: m_fName(("/sys/class/gpio/" + sName).c_str())
{
m_fs.open(m_fName.c_str());
if (m_fs.fail())
{
cout<<"ERROR: attempted to open " << m_fName << " but failed" << endl << endl;
}
else
{
cout << m_fName << " opened" << endl;
}
}
~GpioFileOut()
{
m_fs.close();
cout << m_fName << " closed" << endl << endl;
}
void reOpen()
{
m_fs.close();
m_fs.open(m_fName);
if (m_fs.fail())
{
cout<<"ERROR: attempted to re-open " << m_fName << " but failed" << endl << endl;
}
else
{
cout << m_fName << " re-opened" << endl;
}
}
GpioFileOut& operator<<(const string &s)
{
m_fs << s << endl;
cout << s << " sent to " << m_fName << endl;
return *this;
}
GpioFileOut& operator<<(int n)
{
return *this << to_string(n); //ostringstream
}
bool fail()
{
return m_fs.fail();
}
};
class GpioFileIn
{
private:
ifstream m_fs;
string m_fName;
public:
GpioFileIn(const string& sName)
: m_fs( ("/sys/class/gpio/" + sName).c_str())
, m_fName(("/sys/class/gpio/" + sName).c_str())
{
if (m_fs <= 0 || m_fs.fail())
{
cout<<"ERROR: attempted to open " << m_fName << " but failed" << endl;
}
else
{
cout << m_fName << " opened" << endl;
}
}
~GpioFileIn()
{
m_fs.close();
cout << m_fName << " closed" << endl << endl;
}
void reOpen()
{
m_fs.close();
m_fs.open(m_fName);
if (m_fs <= 0 || m_fs.fail())
{
cout<<"ERROR: attempted to re-open " << m_fName << " but failed" << endl;
}
else
{
cout << m_fName << " re-opened" << endl;
}
}
GpioFileIn& operator>>(string &s)
{
m_fs >> s;
cout << s << " read from " << m_fName << endl;
return *this;
}
bool fail()
{
return m_fs.fail();
}
};
class Gpio
{
public:
static const bool OUT = true;
static const bool IN = false;
static const bool ON = true;
static const bool OFF = false;
static bool setPinDirection(const int pinId, const bool direction)
{
GpioFileOut dirFOut(("gpio" + to_string(pinId) + "/direction").c_str());
if (dirFOut.fail())
{
if (!openPin(pinId))
{
cout << "ERROR! Pin direction not set: Failed to export pin" << endl;
return false;
}
dirFOut.reOpen();
}
dirFOut << (direction == OUT ? "out" : "in");
}
static bool setPinValue(const int pinId, const bool pinValue)
{
string s;
{
GpioFileIn dirFIn(("gpio" + to_string(pinId) + "/direction").c_str());
if (dirFIn.fail())
{
if (!openPin(pinId))
{
cout << "ERROR! Pin not set: Failed to export pin"<<endl;
return false;
}
dirFIn.reOpen();
}
dirFIn >> s;
}
if (strncmp(s.c_str(), "out", 3) == 0)
{
struct stat _stat;
int nTries = 0;
string fname("/sys/class/gpio/gpio"+to_string(pinId)+"/value");
for(;;)
{
if (stat(fname.c_str(), &_stat) == 0)
{
cout << _stat.st_mode << endl;
if (_stat.st_mode & 020 )
break;
}
else
{
cout << "stat failed. (Did the pin get exported successfully?)" << endl;
}
cout << "sleeping until value file appears with correct permissions." << endl;
if (++nTries > 10)
{
cout << "giving up!";
return false;
}
usleep(100*1000);
};
GpioFileOut(("gpio" + to_string(pinId) + "/value").c_str()) << pinValue;
return true;
}
return false;
}
static bool openPin(const int pinId)
{
GpioFileOut fOut("export");
if (fOut.fail())
return false;
fOut << to_string(pinId);
return true;
}
}
int main()
{
Gpio::openPin(17);
Gpio::setPinDirection(17, Gpio::OUT)
Gpio::setPinValue(17, Gpio::ON);
}
The key point is this: without the for(;;) loop that stat's the file, the execution fails, and we can see the permissions change on the file within 100ms.
From a kernel perspective, the 'value' files for each GPIO pin that has been exported are created with mode 0644 and ownership root:root. The kernel does not do anything to change this when you write to the 'direction' file.
The behavior you are describing is due to the operation of the systemd udev service. This service listens for events from the kernel about changes in device state, and applies rules accordingly.
When I tested on my own Pi, I did not experience the behavior you described - the gpio files in /sys are all owned by root:root and have mode 0644, and did not change regardless of direction. However I am running Pidora, and I could not find any udev rules in my system relating to this. I am assuming that Raspbian (or maybe some package you have added to your system) has added such rules.
I did find this thread where some suggested rules are mentioned. In particular this rule which would have the effect you describe:
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'chown -R root:gpio /sys/class/gpio; chmod -R 770 /sys/class/gpio; chown -R root:gpio /sys/devices/virtual/gpio; chmod -R 770 /sys/devices/virtual/gpio'"
You can search in /lib/udev/rules.d, /usr/lib/udev/rules.d and /etc/udev/rules.d for any files containing the text 'gpio' to confirm if you have such rules. By the way, I would be surprised if the change was triggered by changing direction on the pin, more likely by the action of exporting the pin to userspace.
The reason you need to sleep for a while after exporting the device is that until your process sleeps, the systemd service may not get a chance to run and action the rules.
The reason it is done like this, rather than just having the kernel take care of it, is to push policy implementation to userspace in order to provide maximum flexibility without overly complicating the kernel itself.
See: systemd-udevd.service man page and udev man page.
I'm working on my radio transmitter and have just ported it to Linux. Here is the problem:
void input_thread()
{
char buffer[128];
cout << "Waiting for input\n";
for (;;)
{
cout << "say> ";
if (cin.getline(buffer, 127).fail())
// Ctrl+C
break;
else if (strlen(buffer) == 0)
continue;
signal_source.feed(buffer);
}
}
I use a std::thread and hope it break the loop when gets a Ctrl+C. This piece of code works well on Windows but not on Linux. I'm wondering if there is a way to safely break the loop so that I can join the thread without causing deadlock? Thanks.
i have a watchdog stop function placed inside the deconstructor of the process that i executed from my C++ program. Everytime i close using the "X" button on that process QT GUI, it will run thru the codes that i placed in the deconstructor. but when i try to do a Qprocesskill/close/terminate to kill the process in my C++ program, the codes in the deconstructors(of the process) are not being executed. Anyone knows whats wrong or have alternative methods to close the process? Thanks!!!
Btw im on linux.
No objects get torn down when the process abruptly exits with those functions. They're the equivalent to the C function exit(1). Try gracefully exiting the event loop of your QApplication::exec by calling QApplication::quit () which will exit the main event loop inside of exec and allow main to exit normally and allowing all objects that would normally destroy themselves at that point to do so.
Use std::signal to register the handlers for those signals (http://en.cppreference.com/w/cpp/utility/program/signal):
#include <csignal>
#include <iostream>
namespace
{
volatile std::sig_atomic_t gSignalStatus;
}
void signal_handler(int signal)
{
gSignalStatus = signal;
}
int main()
{
// Install a signal handler
std::signal(SIGINT, signal_handler);
std::cout << "SignalValue: " << gSignalStatus << '\n';
std::cout << "Sending signal " << SIGINT << '\n';
std::raise(SIGINT);
std::cout << "SignalValue: " << gSignalStatus << '\n';
}