QFile write does not respond / crashes the application - c++

I'm working on embedded linux and copying files to usb flash drives.
my files:
sourceFile->open(QIODevice::ReadOnly);
targetFile->open(QIODevice::ReadWrite);
the variables
nCopySize = sourceFile->size() / 100;
QByteArray buffer;
and the read write part:
//copy files
for (int count = 0; !(buffer = sourceFile->read(nCopySize + 1)).isEmpty(); count+=(nCopySize + 1))
{
try {
int writeErr = targetFile->write(buffer);
qDebug() << writeErr;
if (writeErr == -1) { //e.g. when device is plugged off
abortCopyFile = true;
}
} catch (const std::exception& ex) {
qDebug() << "catched something:" << ex.what();
//abort copying file... etc.
} catch (...) {
qDebug() << "catched something else";
//abort copying file... etc.
}
//report progress ...
//abort-option
if (abortCopyFile == true)
break;
}
I don't know if the catch part is right, but that's not my actual question. The point is, that when I unplug the USB flash drive while copying the file from the system to the USB flash drive, the line
targetFile->write(buffer);
sometimes responds -1 and sometimes it responds not at all and the application kinda crashes ominously.
So I thought the try-catch would help me but it doesn't. It does not catch anything. The app just crashes.
What can I do about that problem? Restarting the application is the least I want to do.

Related

Cannot connect to the device with QSerialPort

I develop Qt application in C++ under manjaro linux. The goal is to connect with a qC (Nucleo-L476RG Board) and receive data from accelerometer. App can find device on /dev/ttyACM0, but when i try to connect it fails with error "QSerialPort::DeviceNotFoundError". Checking errorString() gives "No such file or directory", but it still can find it in /dev.
I'm in the right group to read the file:
[1]: https://i.stack.imgur.com/CG1yZ.png
I use Qt v.6.2.4, but have build the code with Qt v.5.15.3. I tried to run another person's app that does the same and works under ubuntu, but it didn't work.
Here is my code with the searching and connecting methods. Method addToLogs() just prints logs in textEdit.
void MainWindow::addToLogs(QString message)
{
QString currDateTime = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss");
ui->textEditLogs->append(currDateTime + "\t" + message);
}
void MainWindow::on_pushButtonSearch_clicked()
{
ui->comboBoxDevices->clear();
this->addToLogs("Szukam urządzeń...");
QList<QSerialPortInfo> devices;
devices = QSerialPortInfo::availablePorts();
if(devices.count() > 0)
{
for(int i=0; i<devices.count(); i++)
{
this->addToLogs(devices.at(i).portName());// + " " + devices.at(i).description());
//ui->comboBoxDevices->addItem(devices.at(i).systemLocation());//portName());
ui->comboBoxDevices->addItem(devices.at(i).portName());
}
}
}
void MainWindow::on_pushButtonConnect_clicked()
{
if(ui->comboBoxDevices->count() == 0)
{
this->addToLogs("Nie wykryto żadnych urządzeń!");
return;
}
if(this->device->isOpen())
{
this->addToLogs("Port jest już otwarty!");
return;
}
QString portName = ui->comboBoxDevices->currentText();
//this->device->setPortName(portName);
this->device->setPortName("/dev/ttyACM0");
qDebug() << this->device->portName();
if(device->open(QSerialPort::ReadWrite))
{
this->device->setBaudRate(QSerialPort::Baud9600);
this->device->setParity(QSerialPort::NoParity);
this->device->setDataBits(QSerialPort::Data8);
this->device->setStopBits(QSerialPort::OneStop);
this->device->setFlowControl(QSerialPort::NoFlowControl);
this->addToLogs("Połączono z urządzeniem " + portName);
}
else
{
this->addToLogs("Otwarcie portu szeregowego się nie powiodło!");
this->addToLogs(device->errorString());
qDebug() << this->device->error();
}
}
I will be thankful for help, cause i've benn sitting on it for last 2 or 3 weeks and nothing works.

Google protocol buffer always throw bad allocation exception

I'm newbie in google protocol buffer. And now I have a issue as below:
I have created a simple message in testMessage.proto file:
option optimize_for = SPEED;
message TestMessage
{
optional string foo = 1;
optional string bar = 2;
}
Then I generated this message to testMessage.pb.h and testMessage.pb.cc files and included these files, also added libprotobuf libs to my test project.
Then I wrote a simple code to use this class:
TestMessage testMsg;
testMsg.set_foo("1234"); // set ok
testMsg.set_bar("abcd"); // set ok
string output;
try {
std::cout << testMsg.foo() << std::endl; // output foo ok
testMsg.PrintDebugString(); // throw bad allocation exception here
// testMsg.SerializeToString(&output); // also throw bad allocation exception here
} catch (std::exception ex) {
std::cout << ex.what() << std::endl;
}
This code is very simple, but I cannot understand why it cannot run correctly.
I googled for my issue but there is nowhere mention about it.
Everyone please help me with this issue.

How to read data from the serial port in QT?

I am creating a script in QT for reading the format packages (AA), (BB), etc from serial port. I open the serial port, but when I go to check inside the QByteArray values, comes back that I could not read any value.
This is my code
...
QSerialPort *serialPort = new QSerialPort();
serialPort->setPortName("ttyUSB0");
serialPort->setParity(QSerialPort::NoParity);
serialPort->setBaudRate(QSerialPort::Baud9600, QSerialPort::AllDirections);
serialPort->setStopBits(QSerialPort::OneStop);
serialPort->setFlowControl(QSerialPort::NoFlowControl);
serialPort->open(QIODevice::ReadOnly);
if (serialPort->isOpen()) {
qDebug() << "Serial port is open...";
QByteArray datas = serialPort->readAll();
if (datas.size() == 0) {
qDebug() << "Arrived data: 0";
} else {
for (int i = 0; i < datas.size(); i++){
if (datas.at(i)) {
qDebug() << datas[i];
}
}
}
} else {
qDebug() << "OPEN ERROR: " << serialPort->errorString();
}
serialPort->close();
qDebug() << "...serial port is closed!";
return 0;
...
You called readAll() immediately after open(). It probably took the computer a few nanoseconds to get from one to the other.
At 9600 baud, each byte of data takes slightly more than one millisecond to transfer. It would be absolutely impossible for any data to have arrived in that short an interval, so that's why you got no data.
Serial ports don't begin buffering incoming data until you open them (how could they, what baud rate and other settings would be used for receiving and buffering when no program has the port open?)
Use either a blocking read function of some sort (such as readLine()) or an event loop that reacts to data when it arrives.

boost::filesystem::directory_interatory i(path) crashes on start up in qt creator

for(directory_iterator i(l_path),end_iter; i != end_iter; i++){
string im_name = filename;
//string im_name = i->path().filename().string();
string l_filename = l_path + im_name;
im_name.replace(im_name.begin(),im_name.begin() + 4, string("right"));
string r_filename = r_path + im_name;
Mat lim = imread(l_filename),rim = imread(r_filename);
if(!lim.empty() && !rim.empty()){
l_images.push_back(lim);
r_images.push_back(rim);
}
}
The above crashes on start up and yes the path is there but for some reason it won't run. I have tried this with out the path and it runs. I have no idea what is going wrong. Thanks for any help you can give. below is where i declare it. I am using the latest build of boost and qt creator with open cv to get disparity images for stereo vision, this is what i am using to make the xml file for calibration.
filename = DISTFOLDER + string("stereo_calib.xml");
calib = new calibrator(LEFTFOLDER,RIGHTFOLDER,1.f,5,4,"lImage.png");
calib->calc_image_points(true);
bool done = calib->calibrate();
if(!done){
qDebug("stereo calibration failed");
}
calib->save_info(filename);
Even with try{... }catch blocks it still crashes in QT, I don't know what I changed in my code or the QT environment since it used to work.
Note that when running the app from QT Creator run console it crushes, but running the app directly either from cmd or via explorer works just fine.
The Problem I believe is within QT environment variables being messed up.
The only solution is to append QCoreApplication::applicationDirPath ().toStdString() to the boost::filesystem::directory_iterator iterator(string("tools/adb/"));and make sure the string is what boost expects for path strings.
The try catch block outputs
is_directory failed with The system cannot find the path specified
Here is my current code:
try {
boost::filesystem::directory_iterator iterator(string("tools/adb/"));
for(; iterator != boost::filesystem::directory_iterator(); ++iterator) {
if(is_directory(iterator->path())) {
cout << (iterator->path()) << endl;
adb_s str;
str.path=iterator->path().string();
boost::replace_all(str.path, "/", "\\");
str.path+="\\";
adb_path.push_back(str);
}
}
} catch(const boost::filesystem::filesystem_error& e) {
if(e.code() == boost::system::errc::permission_denied) {
std::cout << "Search permission is denied for one of the directories ";
std::cout << "in the path prefix of \n";
} else {
std::cout << "is_directory failed with ";
std::cout << e.code().message() << '\n';
}
}

A connection is made between server and client but unable to send data via OutputStream in J2ME

I started to program client/server applications in J2ME recently.Now I'm working with c++ builder 2010 indy components (e.g. TidTTCPServer) and J2ME. My application is designed to restart the kerio winroute firewall service from a remote machine.
My server application is written in c++ builder 2010, I've put a TidTCTServer component into a form which binded to 127.0.0.1:4500. That's listening on port 4500 in local machine.
Then i've added a listbox that i need to add every upcoming packets converted to UnicodeString.
//void __fastcall TForm1::servExecute(TIdContext *AContext)
UnicodeString s;
UnicodeString txt;
txt=Trim(AContext->Connection->IOHandler->ReadLn());
otvet->Items->Add(txt);
otvet->ItemIndex=otvet->Items->Count-1;
if (txt=="1") {
AContext->Connection->IOHandler->WriteLn("Suhrob");
AContext->Connection->Disconnect();
}
if (txt=="2") {
AContext->Connection->IOHandler->WriteLn("Shodi");
AContext->Connection->Disconnect();
}
//----------------------------------------------------------------------------
// void __fastcall TForm1::servConnect(TIdContext *AContext)
++counter;
status->Panels->Items[0]->Text="Connections:" + IntToStr(counter);
status->Panels->Items[1]->Text="Connected to " + AContext->Connection->Socket->Binding->PeerIP + ":" + AContext->Connection->Socket->Binding->PeerPort;
and my client side code looks smth like this:
else if (command == send) {
// write pre-action user code here
InputStream is=null;
OutputStream os=null;
SocketConnection client=null;
ServerSocketConnection server=null;
try {
server = (ServerSocketConnection) Connector.open("socket://"+IP.getString()+":"+PORT.getString());
// wait for a connection
client = (SocketConnection) Connector.open("socket://"+IP.getString()+":"+PORT.getString());
// set application-specific options on the socket. Call setSocketOption to set other options
client.setSocketOption(SocketConnection.DELAY, 0);
client.setSocketOption(SocketConnection.KEEPALIVE, 0);
is = client.openInputStream();
os = client.openOutputStream();
// send something to server
os.write("texttosend".getBytes());
// read server response
int c = 0;
while((c = is.read()) != -1) {
// do something with the response
System.out.println((char)c);
}
// close streams and connection
}
catch( ConnectionNotFoundException error )
{
Alert alert = new Alert(
"Error", "Not responding!", null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.ERROR);
switchDisplayable(alert, list);
}
catch (IOException e)
{
Alert alert = new Alert("ERror", e.toString(), null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.ERROR);
switchDisplayable(alert, list);
e.printStackTrace();
}
finally {
if (is != null) {
try {
is.close();
} catch (Exception ex) {
System.out.println("Failed to close is!");
}
try {
os.close();
} catch (Exception ex) {
System.out.println("Failed to close os!");
}
}
if (server != null) {
try {
server.close();
} catch (Exception ex) {
System.out.println("Failed to close server!");
}
}
if (client != null) {
try {
client.close();
} catch (Exception ex) {
System.out.println("Failed to close client!");
}
}
}
my client application gets connected with the server but when i try to send data such as
os.write("texttosend".getBytes());
I cannot get text data on the server using. That's I am not getting sent packets in the server from client.
txt=Trim(AContext->Connection->IOHandler->ReadLn());
Guys, where am I wrong? is the way i'm doing is ok?
Or do I need to use StreamConnection instead of SocketConnection?
And when i use telnet to send data it works cool, strings will be added to listbox
telnet 127.0.0.1 4500
texttosend
23
asf
Any help is appreciated !!!
Thanks in advance!
The main problem is that you are using ReadLn() on the server end. ReadLn() does not exit until a data terminator is encountered (a LF line break character is the default terminator) or if a reading timeout occurs (Indy uses infinite timeouts by default). Your J2ME code is not sending any data terminator, so there is nothing to tell ReadLn() when to stop reading. The reason it works with Telnet is because it does send line break characters.
The other problem with your code is that TIdTCPServer is a multi-threaded component, but your code is updating the UI components in a thread-unsafe manner. You MUST synchronize with the main thread, such as by using Indy's TIdSync and/or TIdNotify classes, in order to update your UI safely from inside of the server's event handlers.
Yes, flush method is necessary to call after sending bytes, but ..... finally....
then i tried to include my connection code in a new thread that implements Runnable worked perfectly. Now I've found where I was wrong!!!!!!!!!!!!!!
That's guys you need to include above code in the following block.
Thread t= new Thread(this);
t.start();
public void run()
{
//here paste the code
}
Try OutputStream.flush()?
If not, try writing to a known working server, instead of one you've created yourself (something like writing "HELO" to an SMTP server), this will help you figure out which end the error is at.