I have an issues trying to launch firefox through QProcess.
Here is the function I used to launch commands (such as firefox, mkdir, ...)
double launch_nowait(string cmd, bool display) {
string command_name = "";
string command_param = "";
bool first_space = false;
for (int p = 0; p < cmd.size(); p++) {
if (!first_space && cmd[p] == ' ') first_space = true;
else {
if (!first_space) command_name += cmd[p];
else command_param += cmd[p];
}
}
cout << "NOWAIT [" << command_name << "][" << command_param << "]" << endl;
QProcess* process;
//process->setWorkingDirectory(".");
//process->waitForFinished();
process->start(QString::fromStdString(command_name), QStringList() << QString::fromStdString(command_param));
return 0;
}
I tried several things such as :
removing parameters,
changing the navigator to chrome
adding a wait
setting the working directory
But it always ends with a seg fault.
The strange thing is that when I use this function to create a directory it works fine.
Thanks for your help,
Related
I have been searching all over for a simple input Pipe example in C++.
Most of the pipes found is old unix style pipes.
Admitting that I am quite unfamiliar with piping, and my purpose is to create a c++ Apache Log pipe, so that all logs can be piped through my program. I assume that the minimum requirement is an input-pipe.
Currently my pipe is listed below.
I have established that when running the command : cat /pathto/access_log | ./myfunction , the output will produce an output like : 0 : 1: 14 HTTP GET found.
And I have established that the pipe gets its input from cin, and not from argv, something that might be stupefying and trivial for the professional programmer.
My current problem now, is that the prgrogram stop when all inputs have been piped in. Trying to type something in the terminal, seem to work, but the input seem to be disregarded and not handled.
But my question is : Is this a properly written input pipe. And if not. What is missing?
void pipecommand(string strcommand, int &cnt1, int &cnt2, bool flag){
//Extra code inserted here to handle http log entries
//-------------
int loc = strcommand.find("GET");
if(loc != string::npos)
{
if(flag){cnt1++;}
else{cnt2++;}
cout << cnt1 << " : " << cnt2 << ": " << loc << " HTTP GET found" << endl;
}
}
int main(int argc, char *argv[])
{
string str_command = "";
string argument = "";
bool argument_f = false;
int counter1 = 0;
int counter2 = 0;
bool isArg = false;
if (argc == 2)
{
argument = argv[1];
argument_f = true;
}
while(getline(cin, str_command)) //getline inserted here
{
if(argument_f){
isArg = true;
pipecommand(argument, counter1, counter2, isArg);
argument_f = false;
}
else{
//getline(cin, str_command);
//Removed and inserted in while
isArg = false;
pipecommand(str_command, counter1, counter2, isArg);
}
}
return 0;
}
This My first node.js and n_api. I have been using PHP/APACHI. But I need the c++ library for my web And I decided to using n_api.
The problem is that the value sent by ajax is always 0 in c++.
I don't know what is problem.
ex) I using a vscode.
const testAddon = require('./build/Release/firstaddon.node');
var http = require('http');
var url = require('url');
var fs = require('fs');
const express = require('express');
const app = express();
bodyParser = require('body-parser');
var port = '1080';
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.post('/server', function(req, res){
var responseData = {};
responseData.pID = req.body.pID;
console.log(responseData.pID); <<============= here, value is correct.
const prevInstance = new testAddon.ClassExample(4.3);
var value = prevInstance.getFile(responseData.pID);
console.log(value);
res.json(responseData);
});
If ajax sends 2, console.log(responseData.pID) //2 appears. It is normal.
Below is the classtest.cpp
Napi::Value ClassTest::GetFile(const Napi::CallbackInfo &info)
{
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
using namespace std;
if (info.Length() != 1 || !info[0].IsNumber())
{
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
}
Napi::Number file_id = info[0].As<Napi::Number>();
int num = this->actualClass_->openFile(file_id); <<== here, file id
return Napi::Number::New(info.Env(), num);
}
And ActualClass.cpp Files showing problems.
int ActualClass::openFile(int id)
{
ifstream fin;
cout << id << endl; <<============================ here, always '0'
filename += to_string(id) += ".txt";
fin.open(filename.c_str(), ios_base::in | ios_base::binary);
if (fin.is_open())
{
while (fin.read((char *)&sdo, sizeof(sdo)))
{
cout << setw(20) << sdo.name << ":"
<< setprecision(0) << setw(12) << sdo.width
<< setprecision(2) << setw(6) << sdo.height
<< setprecision(4) << setw(6) << sdo.size << endl;
slist.push_back(sdo);
}
fin.close();
}
else if (!fin.is_open())
{
cerr << "can't open file " << filename << ".\n";
exit(EXIT_FAILURE);
}
return sdo.size;
}
Only files 1 to 4 are prepared.
But, the argument value entering the function is always 0.
Result is "can't open file 0.txt".
How can I solve it?
Napi::Number file_id = info[0].As<Napi::Number>();
I know here it is converted to an int value that can be handled by C++. Is there anything else I don't know?
Thanks for reading.
You need to cast it to the number with the help of the Napi::Number::Int32Value call. (You can also use Napi::Number::Int64Value for bigger numbers)
Try this.
int file_id = info[0].ToNumber().Int32Value();
Also unrelated to the question, but worth mentioning that when you are doing ThrowAsJavaScriptException() the actual C++ code keeps executing, you better return undefined to avoid nasty bugs.
if (info.Length() != 1 || !info[0].IsNumber())
{
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
return Env.Undefined();
}
A more clean way will be to enable the CPP exceptions and just throw the error in that place.
if (info.Length() != 1 || !info[0].IsNumber())
{
throw Napi::TypeError::New(env, "Number expected");
}
I'm trying to open and read a .conf file in my program using libconfig::readFile(), but it gives me always a FileIOException. I think that the program is unable to locate the file but I don't know where the problem is.
This is the .conf file code:
controlLoopPeriod = 100.0; # ms
saturationMax = [10.0];
saturationMin = [-10.0];
task = { Linear_Velocity = {
type = 0; # 0 equality, 1 inequality
gain = 1.0;
enable = true;
saturation = 10.0;
};
};
priorityLevels = ( { name = "PL_JPosition";
tasks = ["Joint_Position"];
lambda = 0.0001;
threshold = 0.01;
}
);
actions = ( { name = "jPosition";
levels = ["PL_JPosition"];
}
);
states = { State_move = {
minHeadingError = 0.05;
maxHeadingError = 0.2;
};
};
This is where I'm trying to open the file and read it:
bool RobotPositionController::LoadConfiguration() {
libconfig::Config confObj;
// Inizialization
std::string confPath = "home/nimblbot/tpik_ctr_algo/ctrl_rob_nimblbot";
confPath.append("/conf/");
confPath.append(fileName_);
std::cout << "PATH TO CONF FILE : " << confPath << std::endl;
// Read the file. If there is an error, report it and exit.
try {
confObj.readFile(confPath.c_str());
} catch (const libconfig::FileIOException& fioex) {
std::cerr << "I/O error while reading file: " << fioex.what() << std::endl;
return -1;
} catch (const libconfig::ParseException& pex) {
std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine() << " - " << pex.getError() << std::endl;
return -1;
}
conf_->ConfigureFromFile(confObj);
ConfigureTaskFromFile(tasksMap_, confObj);
ConfigurePriorityLevelsFromFile(actionManager_, tasksMap_, confObj);
// Set Saturation values for the iCAT (read from conf file)
iCat_->SetSaturation(conf_->saturationMin, conf_->saturationMax);
ConfigureActionsFromFile(actionManager_, confObj);
//insert states in the map
statesMap_.insert({ states::ID::jPos, stateJPosition_ });
ConfigureSatesFromFile(statesMap_, confObj);
//insert command in the map
commandsMap_.insert({ commands::ID::jPos, commandJPosition_ });
return true;
}
Thanks in advance for any type of help.
It looks to me you are missing a / at the beginning of your home path.
I.e., change:
std::string confPath = "home/nimblbot/tpik_ctr_algo/ctrl_rob_nimblbot";
For:
std::string confPath = "/home/nimblbot/tpik_ctr_algo/ctrl_rob_nimblbot";
I take it you have checked the .conf file exists at:
/home/nimblbot/tpik_ctr_algo/ctrl_rob_nimblbot/conf
I want to store cookie for my commandline application, for now I am using a file base approach where in I am using a file to store the data returned by server for future use in my command line application and encrypt the file.
The code goes like this
if ((sHeader.find("Session_ID")) != std::string::npos)
{
int iFound1 = sHeader.find("{");
int iFound2 = sHeader.find("}", iFound1);
int iLen = iFound2 - iFound1 - 1;
std::string sessionID = sHeader.substr((iFound1 + 1), iLen);
if (!sessionIdSet)
{
std::ofstream outputFile;
outputFile.open("session.txt");
if (outputFile.is_open())
{
outputFile << "Session_ID = " << sessionID << "\n" ;
outputFile << "IP = " << cli.getIP() << "\n";
outputFile.close();
sessionIdSet = true;
}
}
}
What can be a better approach to do it,, one i found is using %appdata% but i need some mechanism that is independent of underlying platform.
I'm writing a small utility which is supposed to launch several commands in parallel using system() and wait for their results for logging purposes. However, even though I'm calling system() on different threads, by looking at my Activity Monitor I only see one instance of each command at a time. It looks like system is internally synchronized on a mutex, and only one execution is allowed at each time, however this looks like a huge limitation, can someone confirm this behavior? Do you have any ideas on how to solve it?
Update by looking at the threads execution flow, it looks like they're effectively synchronizing on a mutex. Is there an alternative system() which doesn't do that?
I should mention I'm using C++11 (w/ clang and libc++) on Mac OS 10.7.5.
Update code is:
void Batch::run()
{
done.clear();
generator->resetGeneration();
while(generator->hasMoreParameters())
{
// Lock for accessing active
unique_lock<mutex> lock(q_mutex, adopt_lock);
// If we've less experiments than threads
if (active.size() < threads)
{
Configuration conf = generator->generateParameters();
Experiment e(executable, conf);
thread t(&Experiment::run, e, reference_wrapper<Batch>(*this));
thread::id id = t.get_id();
active.insert(id);
t.detach();
}
// Condition variable
q_control.wait(lock, [this] { return active.size() < threads; } );
}
}
void Batch::experimentFinished(std::thread::id pos)
{
unique_lock<mutex> lock(q_mutex, adopt_lock);
active.erase(pos);
lock.unlock();
q_control.notify_all();
}
void Experiment::run(Batch& caller)
{
// Generate run command
stringstream run_command;
run_command << executable + " ";
ParameterExpression::printCommandLine(run_command, config);
if (system(run_command.str().c_str()))
stats["success"] = "true";
else
stats["success"] = "false";
caller.experimentFinished(this_thread::get_id());
}
Just to be clear: the spawning and handling of threads works fine and does what it needs to do, but it looks like you can have just one instance of system() running at a time.
Thanks
POSIX has this to say about system(3):
Using the system() function in more than one thread in a process or when the SIGCHLD signal is being manipulated by more than one thread in a process may produce unexpected results.
Due to the way that SIGCHLD must be blocked during the execution, running system calls concurrently doesn't really work. If you want multiple threads to run external tasks, you'll need to write a bit more code (handling fork/exec/wait yourself).
To whoever comes later, popen did the trick, as it doesn't internally keep a mutex. The code to make it work is
FILE* proc;
char buff[1024];
// Keep track of the success or insuccess of execution
if (!(proc = popen(run_command.str().c_str(), "r")))
stats["success"] = "false";
else
stats["success"] = "true";
// Exhaust output
while(fgets(buff, sizeof(buff), proc) != nullptr);
pclose(proc);
In case this helps, I wrote some fork/exec/wait code in C++ a while back. It captures output into a std::string.
As #Mat points out, fork, exec, and wait aren't really designed to be uses in a multi-threaded process.
So this is more useful if multi-process can be a substitute for multi-threaded in your application.
bool Utility::execAndRedirect(std::string command, std::vector<std::string> args, std::string& output, int& status)
{
int error;
int pipefd[2];
int localStatus;
if (pipe(pipefd) == -1)
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
return false;
}
pid_t pid = fork();
if (pid == 0)
{
char** argsC;
argsC = new char*[args.size() + 2];
argsC[0] = new char[command.size() + 1];
strncpy(argsC[0], command.c_str(), command.size());
argsC[0][command.size()] = '\0';
for (size_t count = 0; count < args.size(); count++)
{
argsC[count + 1] = new char[args[count].size() + 1];
strncpy(argsC[count + 1], args[count].c_str(), args[count].size());
argsC[count + 1][args[count].size()] = '\0';
}
argsC[args.size() + 1] = NULL;
close(pipefd[0]);
if (dup2(pipefd[1], STDOUT_FILENO) == -1)
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
exit(1);
}
if (dup2(pipefd[1], STDERR_FILENO) == -1)
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
exit(1);
}
close(pipefd[1]);
if (execvp(command.c_str(), argsC) == -1)
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
exit(1);
}
}
else if (pid > 0)
{
size_t BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE + 1];
close(pipefd[1]);
ostringstream oss;
ssize_t num_b;
while ((num_b = read(pipefd[0], buffer, BUFFER_SIZE)) != 0)
{
buffer[num_b] = '\0';
oss << buffer;
}
output = oss.str();
waitpid(pid, &localStatus, 0);
close(pipefd[0]);
}
else
{
error = errno;
cerr << "Executing command '" << command << "' failed: " << strerror(error) << endl;
return false;
}
if(WIFEXITED(localStatus))
{
status = WEXITSTATUS(localStatus);
//DateTime current = DateTime::now(); //this is a custom class
if(status == 0)
{
return true;
}
else
{
return false;
}
}
else
{
error = errno;
cerr << "Executing command '" << command << "' failed: child didn't terminate normally" << endl;
return false;
}
}