In the following code
SendMessage() is the API called by the user to send a message over USB
UsbDataReceived() is the function called by another thread when data is received on the USB
Task() is the thread created in init() that reads from the queue filled by SendMessage() and calls the low level usb function to send a message
UsbConnected() is the function called by another thread when a USB device is connected.
I need to implement the following behaviour:
Once a message has been sent, no new messages can be sent up to when an answer for the last message has arrived
When UsbConnected() is called, all of the queues must be emptied and if the thread Task() is waiting on the queue AnswerQueue, it has to be unblocked so that it can go back to wait on the queue CommandQueue
An example of my best solution is listed below.
I had to post an EVENT_QUEUE_RESETTED message on both of the queues with a particular order.
Is it possible to achieve the same result in a less cumbersome way?
void UsbhOut(Message_t );
int UsbConnected;
QueueHandle_t MessageQueue;
typedef enum
{
EVENT_QUEUE_RESETTED,
EVENT_NEW_MESSAGE,
EVENT_NEW_ANSWER,
} Event_t;
typedef struct
{
Event_t Event;
uint8_t Data[32];
} CommandQueue_t;
typedef struct
{
Event_t Event;
uint8_t Data[32];
} AnswerQueue_t;
void init(void)
{
MessageQueue = xQueueCreate(sizeof(Message_t), 10);
AnswerQueue = xQueueCreate(sizeof(Message_t), 10);
xTaskCreate(Task, "", 200, NULL, 1, NULL);
}
void UsbConnected(void)
{
CommandEvent.Event = EVENT_QUEUE_RESETTED;
AnswerEvent.Event = EVENT_QUEUE_RESETTED;
UsbConnected = 1;
xQueueReset(MessageQueue);
xQueueReset(AnswerQueue);
/* The order here is fundmental */
xQueueSend(AnswerQueue, &AnswerEvent, 0);
xQueueSend(MessageQeueue, &CommandEvent, 0);
}
int SendMessage(uint8_t * Data)
{
CommandQueue_t CommandEvent;
CommandEvent.Event = EVENT_NEW_MESSAGE;
memcpy(&CommandEvent, Message, 32);
if(xQueueSend(MessageQueue, &CommandEvent, 0) == pdTRUE)
return 0;
else
return -1;
}
void UsbDataReceived(uint8_t * Data)
{
AnswerQueue_t AnswerEvent;
AnswerEvent.Event = EVENT_NEW_ANSWER;
memcpy(AnswerEvent.Data, Data, 32);
xQueueSend(AnswerQueue, &AnswerEvent,0);
}
void Task(void *pvParameters)
{
CommandQueue_t CommandEvent;
AnswerQueue_t AnswerEvent;
CommandCallback_t * Callback;
while(1)
{
xQueueReceive(UsbhStaticData.CommandSenderQueue, &CommandEvent, portMAX_DELAY);
if(CommandEvent.Event == CommandSenderQueueData_t::EVENT_QUEUE_RESETTED)
{
continue;
}
/* Low level Usb fucntion used to send Data */
UsbdSendData(Command.Data);
xQueueReceive(UsbhStaticData.AnswerReceivdQueue, &AnswerEvent, portMAX_DELAY);
if(AnswerEvent.Event == AnswerReceivedQueueData_t::EVENT_QUEUE_RESETTED)
{
continue;
}
else if(AnswerEvent.Event == AnswerReceivedQueueData_t::EVENT_ANSWER_RECEIVED)
{
ParseData(AnswerEvent.Data);
}
}
}
You could use Queue Sets
FreeRTOS Queue Set API
That way you could create a Queue Set containing a queue and a semaphore. Your task would block on the Queue Set. It would then get unblocked by either receiving a message from the queue or you incrementing the semaphore.
Related
We have a Windows app that we're adding a socket interface for remote configuration and data processing. A TIdTCPServer object receives the messages in the OnExecute event. For some messages, however, the OnExecute event is not fired unless the cursor is moved in the main window.
UPDATE: With a lot more experimenting, whether or not the message is processed immediately, or after a long pause, or not at all, seems more random. In all cases, moving the cursor causes the message to be processed immediately. However, it doesn't seem to be specific to a message, or the order of messages.
Updated source code listings: Here's the OnExecute handler:
void __fastcall TSigToolForm::IdTCPServer1Execute(TIdContext *AContext)
{
TIdBytes buffer;
if (ReceiveBuffer(AContext, buffer))
{
try
{
try
{
msg = &buffer[0]; // msg is class member
TThread::Synchronize(0, mProcess); // Doesn't return until mProcess finishes
buffer = IPOK().toByteArray(); // Ack
SendBuffer(AContext, buffer);
}
catch (const std::exception & ex)
{
buffer = IPFailCommand(ex.what()).toByteArray();
SendBuffer(AContext, buffer);
}
catch (const Exception & ex)
{
buffer = IPFailCommand(toStdString(ex.Message)).toByteArray();
SendBuffer(AContext, buffer);
}
catch (const EIdException & ex)
{
throw; // Let Indy have it
}
}
__finally
{
msg = 0;
}
}
}
The mProcess function and the processMessage function it calls. I stripped all but one message type that processMessage handles:
void __fastcall TSigToolForm::mProcess()
{
if (msg) processMessage(msg);
}
void TSigToolForm::processMessage(byte * message)
{
CSLock lock(cs); // RAII class, cs is TCriticalSection
try
{
IPCommand cmd(message);
switch (cmd.ID)
{
case IPCommand::SET_CAD :
{
setObjectCad(cmd);
break;
}
}
}
catch(const std::exception & ex)
{
ShowMessage(ex.what());
}
catch (const EIdException & ex)
{
throw;
}
catch (...)
{
ShowMessage("Exception in processMessage");
}
}
The ReceiveBuffer and SendBuffer functions:
bool ReceiveBuffer(TIdTCPClient * aClient, TIdBytes & ABuffer)
{
return ReceiveBuffer(aClient->IOHandler, ABuffer);
}
bool ReceiveBuffer(TIdContext * AContext, TIdBytes & ABuffer)
{
return ReceiveBuffer(AContext->Connection->IOHandler, ABuffer);
}
bool ReceiveBuffer(TIdIOHandler * IO, TIdBytes & ABuffer)
{
CSLock lock(cs);
try
{
long sz = IO->ReadLongInt();
IO->ReadBytes(ABuffer, sz, false);
return true;
}
catch (const EIdException & ex)
{
throw;
}
return false;
}
bool SendBuffer(TIdIOHandler * IO, const TIdBytes & ABuffer)
{
CSLock lock(cs);
try
{
IO->WriteBufferOpen();
try
{
IO->Write(ABuffer.Length);
IO->Write(ABuffer);
IO->WriteBufferClose();
}
catch(const Exception &)
{
IO->WriteBufferCancel();
throw;
}
}
catch(const EIdException &)
{
throw;
}
catch (...)
{
return false;
}
return true;
}
bool SendBuffer(TIdContext * AContext, const TIdBytes & ABuffer)
{
return SendBuffer(AContext->Connection->IOHandler, ABuffer);
}
bool SendBuffer(TIdTCPClient * aClient, const TIdBytes & aBuffer)
{
return SendBuffer(aClient->IOHandler, aBuffer);
}
For testing I have a separate program that creates and send the various messages, using TIdTCPClient and the same send / receive buffer functions. This is the only connection to the server program. Here's an example:
void TForm16::setPortAndConnect()
{
IdTCPClient1->Port = bdePort->IntValue();
IdTCPClient1->Host = editHost->Text;
IdTCPClient1->Connect();
}
void TForm16::sendCommandToSVST(const TIdBytes & buffer)
{
try
{
setPortAndConnect();
if (SendBuffer(IdTCPClient1, buffer))
{
TIdBytes recv;
//
// Read the response
if (ReceiveBuffer(IdTCPClient1, recv))
{
IPCommand response = IPCommand::fromByteArray(recv);
}
}
}
__finally
{
IdTCPClient1->Disconnect();
}
}
bdePort is an internal TEdit-derived that deals with numerical input. I'm confident that the data itself is correct. It's getting the server to respond that is a problem right now.
I assume at this point that there must be something the program itself is doing that's interfering with the GUI thread or the socket connection or both. I know this is very open-ended, but any hints on what to look for would be appreciated.
This is C++Builder 10.1 update 1, using the classic compiler.
For some messages, however, the OnExecute event is not fired unless the cursor is moved in the main window.
TIdTCPServer is a multi-threaded component, the OnExecute event is fired in a worker thread in a continuous loop for the lifetime of the socket connection. So the ONLY way it could be getting blocked until mouse activity is detected is if your OnExecute code is synchronizing with the main UI thread, and the main UI thread is blocked until window messages are received.
In the code you have shown, the only places where your OnExecute code could be getting blocked are the calls to ReceiveBuffer(), mProcess(), and SendBuffer(). Make sure they are all thread-safe. You did not show the code for any of those methods, or the code for your main UI thread, but mProcess() is being called via TThread::Synchronize() so start with that one and make sure your main UI thread is not blocking mProcess() while it is trying to process a socket message.
BTW, you are catching only STL-based exceptions (derived from std::exception), but you are completely ignoring RTL-based exceptions (derived from System::Sysutils::Exception). And in the case of Indy-based exceptions (which are derived from EIdException, which itself is derived from System::Sysutils::Exception), DO NOT swallow them! If you catch an Indy exception, re-throw it and let TIdTCPServer handle it, otherwise its threads will not be able to detect socket disconnects and clean up properly (unless you manually call AContext->Connection->Disconnect() in your code).
Don't know the Indy version, whatever came with the compiler.
You can find out the Indy version by:
looking for Indy in the IDE's "About" box
right-clicking on any Indy component in the Form Designer at design-time.
reading the Version property of any Indy component at runtime.
UPDATE: Why are you using a critical section around everything? You don't need that.
You are reading/writing a client socket from only 1 thread (the one firing the OnExecute event). Even if you were reading in one thread and writing in another thread, that is safe to do with sockets without placing a lock around the IOHandler. So you don't need a lock around those IOHandler operations at all.
And your mProcess() method is already being serialized by TThread::Synchronize(), so it will only ever run in the main UI thread. If multiple client threads want to call mProcess() at the same time, Synchronize() ensures it runs only one at a time. So you don't need a lock for that, either. However, your use of ShowMessage() inside of mProcess() is problematic, because it runs a secondary message loop that will allow pending Synchronize() requests to run while mProcess() is still running, so you can end up with multiple mProcess() calls overlapping each other. You should not be doing anything inside of a synced method that can cause window messages to be processed. If a synced method throws an exception, you should not try to catch it. Synchronize() catches exceptions and rethrows them in the context of the thread that called Synchronize(), and you already have exception handlers in your OnExecute code.
The only place I see where you should be using any kind of lock, if any at all, would be inside of setObjectCad(), but only if it needs to access data that can be accessed by multiple threads at the same time.
With that said, try something more like this instead:
void ReceiveBuffer(TIdTCPClient * aClient, TIdBytes & ABuffer)
{
ReceiveBuffer(aClient->IOHandler, ABuffer);
}
bool ReceiveBuffer(TIdContext * AContext, TIdBytes & ABuffer)
{
ReceiveBuffer(AContext->Connection->IOHandler, ABuffer);
}
void ReceiveBuffer(TIdIOHandler * IO, TIdBytes & ABuffer)
{
long sz = IO->ReadLongInt();
IO->ReadBytes(ABuffer, sz, false);
}
void SendBuffer(TIdIOHandler * IO, const TIdBytes & ABuffer)
{
IO->WriteBufferOpen();
try
{
IO->Write(ABuffer.Length);
IO->Write(ABuffer);
IO->WriteBufferClose();
}
catch(const Exception &)
{
IO->WriteBufferCancel();
throw;
}
}
void SendBuffer(TIdContext * AContext, const TIdBytes & ABuffer)
{
SendBuffer(AContext->Connection->IOHandler, ABuffer);
}
void SendBuffer(TIdTCPClient * aClient, const TIdBytes & aBuffer)
{
SendBuffer(aClient->IOHandler, aBuffer);
}
void __fastcall TSigToolForm::IdTCPServer1Execute(TIdContext *AContext)
{
TIdBytes buffer;
ReceiveBuffer(AContext, buffer);
try
{
msg = &buffer[0]; // msg is class member
TThread::Synchronize(0, mProcess); // Doesn't return until mProcess finishes
buffer = IPOK().toByteArray(); // Ack
SendBuffer(AContext, buffer);
}
catch (const std::exception & ex)
{
buffer = IPFailCommand(ex.what()).toByteArray();
SendBuffer(AContext, buffer);
}
catch (const Exception & ex)
{
buffer = IPFailCommand(toStdString(ex.Message)).toByteArray();
SendBuffer(AContext, buffer);
if (dynamic_cast<const EIdException *>(&ex))
throw;
}
catch (...)
{
buffer = IPFailCommand("Unknown exception").toByteArray();
SendBuffer(AContext, buffer);
}
}
void __fastcall TSigToolForm::mProcess()
{
if (msg) processMessage(msg);
}
void TSigToolForm::processMessage(byte * message)
{
IPCommand cmd(message);
switch (cmd.ID)
{
case IPCommand::SET_CAD :
{
setObjectCad(cmd);
break;
}
}
}
void TSigToolForm::setObjectCad(const IPCommand &cmd)
{
// here is where you should be using CSLock, if at all...
}
void TForm16::setPortAndConnect()
{
IdTCPClient1->Port = bdePort->IntValue();
IdTCPClient1->Host = editHost->Text;
IdTCPClient1->Connect();
}
void TForm16::sendCommandToSVST(const TIdBytes & buffer)
{
setPortAndConnect();
try
{
// Send the command
SendBuffer(IdTCPClient1, buffer);
// Read the response
TIdBytes recv;
ReceiveBuffer(IdTCPClient1, recv);
IPCommand response = IPCommand::fromByteArray(recv);
}
__finally
{
IdTCPClient1->Disconnect();
}
}
I am working on Ubuntu 12.04.2 LTS. I have a strange problem with pthread_kill(). The following program ends after writing only "Create thread 0!" to standard output. The program ends with exit status 138.
If I uncomment "usleep(1000);" everything executes properly. Why would this happen?
#include <nslib.h>
void *testthread(void *arg);
int main() {
pthread_t tid[10];
int i;
for(i = 0; i < 10; ++i) {
printf("Create thread %d!\n", i);
Pthread_create(&tid[i], testthread, NULL);
//usleep(1000);
Pthread_kill(tid[i], SIGUSR1);
printf("Joining thread %d!\n", i);
Pthread_join(tid[i]);
printf("Joined %d!", i);
}
return 0;
}
void sighandlertest(int sig) {
printf("print\n");
pthread_exit();
//return NULL;
}
void* testthread(void *arg) {
struct sigaction saction;
memset(&saction, 0, sizeof(struct sigaction));
saction.sa_handler = &sighandlertest;
if(sigaction(SIGUSR1, &saction, NULL) != 0 ) {
fprintf(stderr, "Sigaction failed!\n");
}
printf("Starting while...\n");
while(true) {
}
return 0;
}
If the main thread does not sleep a bit before raising the SIGUSR1, the signal handler for the thread created most propably had not been set up, so the default action for receiving the signal applies, which is ending the process.
Using sleep()s to synchronise threads is not recommended as not guaranteed to be reliable. Use other mechanics here. A condition/mutex pair would be suitable.
Declare a global state variable int signalhandlersetup = 0, protect access to it by a mutex, create the thread, make the main thread wait using pthread_cond_wait(), let the created thread set up the signal handle for SIGUSR1, set signalhandlersetup = 0 and then signal the condition the main thread is waiting on using pthread_signal_cond(). Finally let the main thread call pthread_kill() as by your posting.
I am writing a multi-threaded application using Borland C++ (Delphi Forms). I have recently learned that I can use Windows' Messaging Service within these classes when I call the PostThreadMessage() function:
System = new STSystem(SystemName,1000,1,NULL);
while (PostThreadMessage(System->ThreadID,ST_MSG_SYSTEM_INIT,0,0) == 0)
{
Sleep(0);
};
The above seems to work just fine. The issue lies on the retrieval end of this process inside of the Thread Execution function:
void __fastcall STSystem::Execute()
{
ST_Message STMSG;
while(FStatus != Destroyed)
{
FHeartBeat++;
if(GetMessage(MSG,NULL,ST_MSG_SYSTEM_START,ST_MSG_SYSTEM_END))
{
STMSG.Value = MSG->wParam;
if((STMSG.dSYS + (8*STMSG.dSEC) + (64*STMSG.dDEP)) == FSystemID)
{
RXMessages[RxQueueIn++] = STMSG.MSG; // Message
RXMessages[RxQueueIn++] = MSG->lParam; // Data
}
}
if(TaskList->Count>0)
ProcessTask();
if(RxQueueIn!=RxQueueOut)
ProcessRxMessage();
if(TxQueueIn!=TxQueueOut)
ProcessTxMessage();
Sleep(0);
};
}
The above works for about two thread cycles and then stops; the thread stops, not the program. I have tried using the PeekMessage() function instead of the GetMessage() function in the IF clause following the FHeartbeat++ counter. This prevents the thread from stopping however, the INIT message sent in the first block of code is still not found.
I hope this example is not too specific. I have tried to leave in anything that was pertinent. Basically, this is a message pump for a class that has no window.
GetMessage() blocks the calling thread when there are no messages to retrieve. Like Luis said, you need to make sure the thread has a message queue before you start posting messages to it, and you need to check the return value of PostThreadMessage() for failures. A message queue is not created in a thread until any user32.dll function is called within the thread for the first time. For example:
System = new STSystem(SystemName,1000,1,NULL);
while (!System->Ready)
Sleep(100);
if (!PostThreadMessage(System->ThreadID,ST_MSG_SYSTEM_INIT,0,0))
{
DWORD err = GetLastError();
//...
}
void __fastcall STSystem::Execute()
{
// create a message queue
PeekMessage(MSG, NULL, 0, 0, PM_NOREMOVE);
Ready = true;
ST_Message STMSG;
while(FStatus != Destroyed)
{
FHeartBeat++;
if(GetMessage(MSG,NULL,ST_MSG_SYSTEM_START,ST_MSG_SYSTEM_END)) // or PeekMessage()
{
STMSG.Value = MSG->wParam;
if((STMSG.dSYS + (8*STMSG.dSEC) + (64*STMSG.dDEP)) == FSystemID)
{
RXMessages[RxQueueIn++] = STMSG.MSG; // Message
RXMessages[RxQueueIn++] = MSG->lParam; // Data
}
}
if(TaskList->Count>0)
ProcessTask();
if(RxQueueIn!=RxQueueOut)
ProcessRxMessage();
if(TxQueueIn!=TxQueueOut)
ProcessTxMessage();
Sleep(0);
};
}
To send messages to a tread it must have a message queue, in the remarks section of this link:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644946(v=vs.85).aspx
you can fine the steps reqired to create a message queue for a thread.
By the way, if PostThreadMessage returns 0 (FALSE), there is an error and you must check the value returned by GetLastError.
I used Eclispse Indigo + CDT 8.0.2 + cygwin to develope a multi-thread systerm, the code is below:
pthread_mutex_t mutexCmd = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t signalCmd = PTHREAD_COND_INITIALIZER;
void * Func(void * arg)
{
int iStatus;
while (1)
{
int a = 1;
pthread_cleanup_push(pthread_mutex_unlock, &mutexCmd);
pthread_mutex_lock(&mutexCmd);
iStatus = pthread_cond_wait(&signalCmd, &mutexCmd);
if (iStatus) {
err_abort(iStatus, "signalCmd status error");
}
if(arg->Cmd != navi_Go) //Just a command tag;
{
pthread_mutex_unlock(&(pNaviCtrl->mutexCmd));
continue;
}
//do some work
//.....
pthread_mutex_unlock(&mutexCmd);
pthread_cleanup_pop(1);
}
//pthread_detach(pthread_self());
return NULL;
}
int main()
{
int iStatus = 0;
pthread = tid;
iStatus = pthread_create(&tid;NULL, Func, NULL);
if(iStatus)
{
err_abort(iStatus, "Start pthread error");
}
// do some work
...
//Cancel thread
void * retval;
iStatus = pthread_cancel(tid)
iStatus = pthread_join(tid; &retval);
if(iStatus){
err_abort(iStatus,"Stop thread error");
}
return iStatus;
}
where program run, it stop at "iStatus = pthread_join(tid1; &retval);" couldn't go forward anymore, I think the thread could be happed to deadlock, but can't find the reason. I supposed after call pthread_cancel(), the thread will exit and return to the pthread_join(),
who can tell me what's wrong with my code?
Don't put cleanup_push and _pop inside the while loop. Don't call them more than once. If you look at them, they are macros that wrap the code between them in { }. They setup a longjump that is used when you call pthread_cancel.
pthread_cleanup_pop(1) tells the pthread library to not only pop the cleanup entry off the stack, but to also execute it. So that call will also implicitly call:
pthread_mutex_unlock(&mutexCmd);
Since you've already unlocked the mutex, that call has undefined behavior (assuming the mutex type is PTHREAD_MUTEX_NORMAL). I imagine that call is just never returning or something.
Note that your code has other problems handing the cleanup - if you execute the continue for the loop, you'll call pthread_cleanup_push() a second time (or more), which will add another cleanup context.
There may be other problems (I'm not very familiar with pthread_cancel()).
My pthread_detach calls fail with a "Bad file descriptor" error. The calls are in the destructor for my class and look like this -
if(pthread_detach(get_sensors) != 0)
printf("\ndetach on get_sensors failed with error %m", errno);
if(pthread_detach(get_real_velocity) != 0)
printf("\ndetach on get_real_velocity failed with error %m", errno);
I have only ever dealt with this error when using sockets. What could be causing this to happen in a pthread_detach call that I should look for? Or is it likely something in the thread callback that could be causing it? Just in case, the callbacks look like this -
void* Robot::get_real_velocity_thread(void* threadid) {
Robot* r = (Robot*)threadid;
r->get_real_velocity_thread_i();
}
inline void Robot::get_real_velocity_thread_i() {
while(1) {
usleep(14500);
sensor_packet temp = get_sensor_value(REQUESTED_VELOCITY);
real_velocity = temp.values[0];
if(temp.values[1] != -1)
real_velocity += temp.values[1];
} //end while
}
/*Callback for get sensors thread*/
void* Robot::get_sensors_thread(void* threadid) {
Robot* r = (Robot*)threadid;
r->get_sensors_thread_i();
} //END GETSENSORS_THREAD
inline void Robot::get_sensors_thread_i() {
while(1) {
usleep(14500);
if(sensorsstreaming) {
unsigned char receive;
int read = 0;
read = connection.PollComport(port, &receive, sizeof(unsigned char));
if((int)receive == 19) {
read = connection.PollComport(port, &receive, sizeof(unsigned char));
unsigned char rest[54];
read = connection.PollComport(port, rest, 54);
/* ***SET SENSOR VALUES*** */
//bump + wheel drop
sensor_values[0] = (int)rest[1];
sensor_values[1] = -1;
//wall
sensor_values[2] = (int)rest[2];
sensor_values[3] = -1;
...
...
lots more setting just like the two above
} //end if header == 19
} //end if sensors streaming
} //end while
} //END GET_SENSORS_THREAD_I
Thank you for any help.
The pthread_* functions return an error code; they do not set errno. (Well, they may of course, but not in any way that is documented.)
Your code should print the value returned by pthread_detach and print that.
Single Unix Spec documents two return values for this function: ESRCH (no thread by that ID was found) and EINVAL (the thread is not joinable).
Detaching threads in the destructor of an object seems silly. Firstly, if they are going to be detached eventually, why not just create them that way?
If there is any risk that the threads can use the object that is being destroyed, they need to be stopped, not detached. I.e. you somehow indicate to the threads that they should shut down, and then wait for them to reach some safe place after which they will not touch the object any more. pthread_join is useful for this.
Also, it is a little late to be doing that from the destructor. A destructor should only be run when the thread executing it is the only thread with a reference to that object. If threads are still using the object, then you're destroying it from under them.