PDA

View Full Version : Program crashes after sending data over libusb/Qthread for 3d time



sisco
3rd December 2009, 11:56
yet another problem! i dont think this has naything to do with libusb but more with the Thread im running.

in my main thread i call a function that sets a character array in the 2nd thread (usbcom) and set a boolean to indicate there is data to send.


void Project::sendSettings()
{
QString a;
QMessageBox box;
unsigned char *b;
int r, transf;
if (ui->checkBox_RPM->isChecked())
{
sprintf((char*)b,"*1 %d %d %d",ui->spinBox_RPM->value(), ui->spinBox_KOPPEL->value(), ui->spinBox_over->value());
a.append((const char*)b);
usbcom->data = b;
usbcom->send = true;
}
else if (ui->checkBox_TEMP->isChecked())
{
sprintf((char*)b,"*0 %d %d", (char)ui->spinBox_TEMP->value(), (char)ui->spinBox_over->value());
a.append((const char*)b);
usbcom->data = b;
usbcom->send = true;
}
else
{
box.setText("Must at least check one option!");
box.exec();
}

the above function is called by this SLOT:


void Project::button_send()
{
if(!usbcom->isRunning())
{
if(checkConnection())
{
sendSettings();
}
}
else
{
sendSettings();
}
}

placing a breakpoint on the first line of this slot shows me that when checking "if(!usbcom->isRunning)" for the thirth time stops the program with a segmentation fault.
gdb output:


Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb6d64700 (LWP 20232)]
0xb71bddd9 in QMutex::lock (this=0x9309cdc)
at /var/tmp/qt-x11-src-4.5.3/src/corelib/thread/qmutex.cpp:152
152 /var/tmp/qt-x11-src-4.5.3/src/corelib/thread/qmutex.cpp: No such file or directory.
in /var/tmp/qt-x11-src-4.5.3/src/corelib/thread/qmutex.cpp


what could cause this?

help is much appreciated

Sisco

wysota
3rd December 2009, 12:07
So where is the thread in all this?

sisco
3rd December 2009, 12:18
So where is the thread in all this?


void UsbCom::run()
{
int r;
r = libusb_init(NULL);
send = false;
if (r < 0)
{
emit error("Failed to initialize USB!");

}
devh = libusb_open_device_with_vid_pid(NULL, idVENDOR, idPRODUCT);
if(!devh)
{
emit error("Could not locate device");
}
else
{
r = libusb_kernel_driver_active (devh, 0);
if (r != 0)
{
if(r==1)
{
r = libusb_detach_kernel_driver(devh, 0);
if (r > 0)
{
emit error("some other random error:"+ QString::number(r));
}
}
}
r = libusb_claim_interface(devh, 0);
if (r < 0)
{
emit error("usb_claim_interface error"+ QString::number(r));
}
int a = 0;
unsigned char irqbuf[64];
irq_transfer = libusb_alloc_transfer(0);
libusb_fill_interrupt_transfer(irq_transfer, devh, EP_INTR_IN, irqbuf,sizeof(irqbuf), ep_irq_in_cb, &a, 0);
r = libusb_submit_transfer(irq_transfer);
while(1)
{
if(send)
{
sendData();
}
if (a == 1)
{
emit dataRecieved(irqbuf);
a = 0;
}
r = libusb_handle_events(NULL);
}
}
libusb_close(devh);
}

void UsbCom::sendData()
{
int r,transf;
QString a;
a.append((const char*)data);
r = libusb_interrupt_transfer(devh, EP_INTR_OUT, data, a.length(),&transf,1000);
if (r == 0)
{
emit error("Configuration sent");
}
send = false;
}

void ep_irq_in_cb(libusb_transfer *transfer)
{
if(transfer->status != LIBUSB_TRANSFER_COMPLETED)
{
fprintf(stderr, "uncompleted transter\n");
}
else
{
int *data = static_cast<int*>(transfer->user_data);
*data = 1;
}

if (libusb_submit_transfer(transfer) < 0)
{
fprintf(stderr,"could not resubmit irq \n");
//exit(1);
}
}

sorry about that :)

wysota
3rd December 2009, 12:22
How about doing proper synchronization of shared variables?

sisco
3rd December 2009, 12:47
im sorry, i am still very new to this.
i have read about QMutex and QWaitCondition but i cant seem to figure out how to implement this in my code.

i tried different aproaches:


void UsbCom::run()
{
int r;
r = libusb_init(NULL);
send = false;
if (r < 0)
{
emit error("Failed to initialize USB!");
}
devh = libusb_open_device_with_vid_pid(NULL, idVENDOR, idPRODUCT);
if(!devh)
{
emit error("Could not locate device");
}
else
{
r = libusb_kernel_driver_active (devh, 0);
if (r != 0)
{
if(r==1)
{
r = libusb_detach_kernel_driver(devh, 0);
if (r > 0)
{
emit error("some other random error:"+ QString::number(r));
}
}
}
r = libusb_claim_interface(devh, 0);
if (r < 0)
{
emit error("usb_claim_interface error"+ QString::number(r));
}
int a = 0;
unsigned char irqbuf[64];
irq_transfer = libusb_alloc_transfer(0);
libusb_fill_interrupt_transfer(irq_transfer, devh, EP_INTR_IN, irqbuf,sizeof(irqbuf), ep_irq_in_cb, &a, 0);
r = libusb_submit_transfer(irq_transfer);
while(1)
{
wait.wait(mutex); //QMutex *mutex
if(send)
{
sendData();
}
if (a == 1)
{
emit dataRecieved(irqbuf);
a = 0;
}
r = libusb_handle_events(NULL);
}
}
libusb_close(devh);
}

void UsbCom::sendData()
{
int r,transf;
QString a;
a.append((const char*)data);
r = libusb_interrupt_transfer(devh, EP_INTR_OUT, data, a.length(),&transf,1000);
if (r == 0)
{
emit error("Configuration sent");
}
send = false;
}

void ep_irq_in_cb(libusb_transfer *transfer)
{
if(transfer->status != LIBUSB_TRANSFER_COMPLETED)
{
fprintf(stderr, "uncompleted transter\n");
}
else
{
int *data = static_cast<int*>(transfer->user_data);
*data = 1;
}

if (libusb_submit_transfer(transfer) < 0)
{
fprintf(stderr,"could not resubmit irq \n");
//exit(1);
}
}


usbcom->mutex = &mutex


void Project::sendSettings()
{
QString a;
QMessageBox box;
unsigned char *b;
int r, transf;
if (ui->checkBox_RPM->isChecked())
{
sprintf((char*)b,"*1 %d %d %d",ui->spinBox_RPM->value(), ui->spinBox_KOPPEL->value(), ui->spinBox_over->value());
a.append((const char*)b);
usbcom->data = b;
usbcom->send = true;
}
else if (ui->checkBox_TEMP->isChecked())
{
sprintf((char*)b,"*0 %d %d", (char)ui->spinBox_TEMP->value(), (char)ui->spinBox_over->value());
a.append((const char*)b);
usbcom->data = b;
usbcom->send = true;
}
else
{
box.setText("Must at least check one option!");
box.exec();
}
usbcom->wait.wakeAll();


this compiles fine but still gives a seg fault.
could you please explain me a little on how i should implement this?

wysota
3rd December 2009, 13:06
Learn to use QMutex. There is a nice example of protecting a shared variable in its docs.

By the way, there is no reason for you to use threads here.

sisco
3rd December 2009, 14:38
how would i get this so i dont need to use a thread.
right now the thread has a "while(1)" loop to check for a completed transfer.
i cant see a way to have this running without hanging the main thread.

wysota
3rd December 2009, 16:23
how would i get this so i dont need to use a thread.
right now the thread has a "while(1)" loop to check for a completed transfer.
i cant see a way to have this running without hanging the main thread.

Use signals and slots (probably with a timer) instead of the while loop. There is no point in using up all your cpu resources without a reason.