I have encountered bounded buffer problem in my project, For solving
this, im using 2 semaphores Full and empty.
Write operation waits for empty semaphore signal and signals full
semaphore after finishing write.
Read operation waits for Full semaphore signal and signals Empty
semaphore after read.
Since im using blocking calls for read and write, each read and
write happens in sequence.
i'm implementing this in VC++ in windows, but im facing windows
errorcode:298 while signalling empty semaphore which says Too many posts were made to a semaphore.
what would be the possible causes for the error 'too may posts were
made to a semaphore' ?
List item
semaphore creation:
string semName = m_mqName;
semName.append(SEMAPHORE_FULL_NAME_SUFFIX);
cout<<"\n <MessageQueue<DType, size>::CreateMsgQSemaphores ()> Semaphore name = "<<semName<<endl;
m_mqFullSemaphore = CreateSemaphore(
NULL, // default security attributes
0, // initial count
size, // maximum count
semName.c_str()); //semaphore name
if (m_mqFullSemaphore == nullptr)
{
cout<<"ERROR::CreateSemaphore Failed, Name:"<<semName<<",error code:"<<GetLastError()<<endl;
CloseHandle(m_mqMutex); // close the existing m_mqMutex
createSemaphoresStatus = CreateMsgQSemaphoresFailedError;
}
else if (ERROR_ALREADY_EXISTS == GetLastError())
{
cout<<"\n <MessageQueue<DType, size>::CreateMsgQSemaphores ()>::WARNING: 'full' Semaphore exist.. "<<semName<<endl;
}
else
//cout<<"***INFO:: semaphore created: m_mqFullSemaphore= "<<m_mqFullSemaphore<<endl;
//------------------------------------------Empty semaphore creation--------------------------------------------//
semName = m_mqName;
semName.append(SEMAPHORE_EMPTY_NAME_SUFFIX);
//cout<<"\n <MessageQueue<DType, size>::CreateMsgQSemaphores ()> Semaphore name = "<<semName<<endl;
m_mqEmptySemaphore = CreateSemaphore(
NULL, // default security attributes
size, // initial count
size, // maximum count
semName.c_str()); // semaphore Name
if(m_mqEmptySemaphore == nullptr)
{
cout<<"\n <MessageQueue<DType, size>::CreateMsgQSemaphores ()>::ERROR: Create empty Semaphore failed.. "<<semName<<endl;
CloseHandle(m_mqMutex); // close the existing m_mqMutex
createSemaphoresStatus = CreateMsgQSemaphoresFailedError;
}
Consumer thread (reader in my project)
DWORD dwFullSemaphoreWaitResult = WaitForSingleObject(m_mqFullSemaphore,
timeoutVal);//wair for full semaphore
if(dwFullSemaphoreWaitResult== WAIT_OBJECT_0) // got the full semaphore
{
//proceed further
DWORD dwMutexWaitResult = WaitForSingleObject( m_mqMutex, timeoutVal); // no time-out interval
//Queue_Mutex_Handler mutexHandler(m_mqMutex);
//RAII
LOG_MSG("SUCCESS: to aquire m_mqFullSemaphore:"<<m_mqName);
switch (dwMutexWaitResult)
{
case WAIT_OBJECT_0: // got ownership of the mutex
{
LOG_MSG("SUCCESS: to aquire m_mqMutex:"<<m_mqName);
size_t qSize = 0;
if(! m_pMsgQueueImpl->Dequeue(destMsg,qSize))
{
LOG_MSG("SUCCESS: Reached here:"<<m_mqName);
LOG_MSG("ERROR: Dequeue failed, MSG Queue is Empty:"<< m_mqName);
//ReleaseMutex(m_mqMutex);
execResult = MQState_Queue_Empty_Error;
if(0 == ReleaseMutex(m_mqMutex))
{
LOG_MSG("Release mutex error:"<<GetLastError());
}
}
else
{
int semCount = 0;
LOG_MSG("MQ POP successful:"<< m_mqName<<", qSize="<<qSize);
//ReleaseMutex(m_mqMutex);
if(0 == ReleaseMutex(m_mqMutex))
{
LOG_MSG("Release mutex error:"<<GetLastError());
}
if ( 0 == ReleaseSemaphore(
m_mqEmptySemaphore, // handle to semaphore
1, // increase count by one
NULL)) // not interested in previous count
{
//LOG_MSG("semCount = "<<semCount);
LOG_MSG("Release Empty Semaphore error: "<<GetLastError());
}
else
{
//LOG_MSG("semCount = "<<semCount);
LOG_MSG("empty Semaphore signalled successfully");
}
return (int)qSize;
}
break;
}
case WAIT_TIMEOUT:
{
LOG_MSG("ERROR: Failed to aquire Mutex:"<<m_mqName<<", due to Timeout:"<<timeoutVal);
execResult = MQState_QOpTimeOut_Error;
break;
}
default: // The thread got ownership of an abandoned mutex
{
LOG_MSG("ERROR: Failed to aquire Mutex:"<<m_mqName<<", due to GetLastError:"<<GetLastError());
execResult = MQState_Queue_Unhandled_Error;
}
} // end of switch (dwMutexWaitResult)
}
else if(dwFullSemaphoreWaitResult == WAIT_TIMEOUT)
{
LOG_MSG("ERROR: Failed to aquire m_mqFullSemaphore:"<<m_mqName<<", due to Timeout:"<<timeoutVal);
execResult = MQState_QOpTimeOut_Error;
}
else
{
LOG_MSG("ERROR: Failed to aquire m_mqFullSemaphore:"<<m_mqName<<", GetLastError:"<<GetLastError());
execResult = MQState_Queue_Unhandled_Error;
}
if(execResult != MQState_QOp_Success)
return execResult;
//=================================================================================================
//LOG_FUNC_END;
return execResult;
Producer thread
MSG_QUEUE_STATUS execResult = MQState_QOp_Success;
//Wait for empty semaphore
DWORD dwSemaphoreWaitResult = WaitForSingleObject( m_mqEmptySemaphore, // handle to mutex
timeoutValInMs); // time-out interval
LOG_MSG("m_mqEmptySemaphore: "<<m_mqEmptySemaphore);
LOG_MSG("Got the m_mqEmptySemaphore");
//Wait for mutex
if(dwSemaphoreWaitResult == WAIT_OBJECT_0)
{
DWORD dwMutexWaitResult = WaitForSingleObject( m_mqMutex, // handle to mutex
timeoutValInMs); // time-out interval
//Queue_Mutex_Handler mutexHandler(m_mqMutex);
LOG_MSG("Got the m_mqMutex");
switch(dwMutexWaitResult)
{
case WAIT_OBJECT_0:
LOG_MSG("going to send Message");
if(m_pMsgQueueImpl->Enqueue(srcMsg) )
{
LOG_MSG("Message Sent successfully");
//int semCount;
if(0 == ReleaseMutex(m_mqMutex))
{
LOG_MSG("Release mutex error:"<<GetLastError());
}
if ( 0 == ReleaseSemaphore(
m_mqFullSemaphore, // handle to semaphore
1, // increase count by one
NULL)) // not interested in previous count
{
//LOG_MSG("semCount = "<<semCount);
LOG_MSG("Release full Semaphore error: "<<GetLastError());
}
else
{
//LOG_MSG("semCount = "<<semCount);
LOG_MSG("full Semaphore signalled successfully");
}
///++++++++++++++
}
else
{
LOG_MSG("ERROR: Enqueue failed, MSG Queue is Full, QName = "<< m_mqName);
if(0 == ReleaseMutex(m_mqMutex))
{
LOG_MSG("Release mutex error:"<<GetLastError());
}
execResult = MQState_Queue_Full_Error;
}
break;
case WAIT_TIMEOUT:
LOG_MSG("ERROR: Failed to aquire MsgQueue Mutex:"<<m_mqName<<", due to Timeout:"<<timeoutValInMs);
execResult = MQState_QOpTimeOut_Error;
break;
default:
LOG_MSG("ERROR: Failed to aquire MsgQueue Mutex:"<<m_mqName);
execResult = MQState_Queue_Unhandled_Error;
}//switch ends
}
else if(WAIT_TIMEOUT==dwSemaphoreWaitResult)
{
LOG_MSG("ERROR: Failed to aquire MsgQueue semaphore:"<<m_mqName<<", due to Timeout:"<<timeoutValInMs);
execResult = MQState_QOpTimeOut_Error;
}
else
{
LOG_MSG("ERROR: Failed to aquire MsgQueue semaphore:"<<m_mqName);
execResult = MQState_Queue_Unhandled_Error;
}
//RAII
//LOG_FUNC_END;
return execResult;
Related
I everyone,
I'm trying to write on serial and also the serial should wait until all bytes are sent.
how can the serial wait to send all bytes?
I was surfing on the internet that I saw this.then, I tried to use the samples. unluckily, they didn't work well.
For example, I tried for use the following code:
BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)
{
OVERLAPPED osWrite = {0};
DWORD dwWritten;
DWORD dwRes;
BOOL fRes;
// Create this write operation's OVERLAPPED structure's hEvent.
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
// error creating overlapped event handle
return FALSE;
// Issue write.
if (!WriteFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite)) {
if (GetLastError() != ERROR_IO_PENDING) {
// WriteFile failed, but isn't delayed. Report error and abort.
fRes = FALSE;
}
else
// Write is pending.
dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
switch(dwRes)
{
// OVERLAPPED structure's event has been signaled.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, FALSE))
fRes = FALSE;
else
// Write operation completed successfully.
fRes = TRUE;
break;
default:
// An error has occurred in WaitForSingleObject.
// This usually indicates a problem with the
// OVERLAPPED structure's event handle.
fRes = FALSE;
break;
}
}
}
else
// WriteFile completed immediately.
fRes = TRUE;
CloseHandle(osWrite.hEvent);
return fRes;
}
But, it doesn't wait to send all bytes. after WriteFile(..) I expect to wait. But, it'll reach to this line.
else
// WriteFile completed immediately.
fRes = TRUE; <--------------------------- this line
And then it returns true.
why doesn't it wait ?
==========Edit========
It's my current function for writing to serial but still it doesn't wait.
int RS232_SendBuf(int comport_number, unsigned char *buf, int size)
{
int n;
DWORD dwCommEvent;
DWORD dwStoredFlags;
dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | \
EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY;
if (!SetCommMask(Cport[comport_number], dwStoredFlags)) {
// Error setting communications mask
return FALSE;
}
if(WriteFile(Cport[comport_number], buf, size, (LPDWORD)((void *)&n), NULL))
{
if (WaitCommEvent(Cport[comport_number], &dwCommEvent, NULL)) {
// An error occurred waiting for the event.
return FALSE;
}
else {
return(n);
}
}
//while (!PurgeComm(Cport[comport_number], PURGE_TXABORT));
return(-1);
}
I've got a child thread that calls WaitForMultipleObjects() and blocks waiting for, among other things, an incoming message over COM4. Attached to the other side of COM4 is a board sending a message once every five seconds.
The problem is, WaitForMultipleObjects() is only notified that a message was received when the read buffer I allocated for it is full, rather than becoming notified whenever a single message is transmitted.
The weird part is that this behavior changes if I connect to the board with putty, close putty, and then reopen my application - WaitForMultipleObjects() will thereafter return whenever a message is received, buffer filled or not. This behavior is preferable, and I would like to know what putty is doing so that I may have it enabled all the time.
I checked the DCB object returned from GetCommState() both with and without using Putty, and it doesn't appear that Putty is changing the structure in a way that I am not already doing.
Here is the code initializing the HANDLE object for the com port (referred to as "hCom"):
bool init(struct ReadComArg readComArg) {
BOOL fSuccess;
log(comPort);
// Open a handle to the specified com port.
hCom = CreateFile(comPort,
GENERIC_READ | GENERIC_WRITE,
0, // must be opened with exclusive-access
NULL, // default security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // can't write in one thread while blocked for a read in another unless port is declared overlapped
NULL); // hTemplate must be NULL for comm devices
if (hCom == INVALID_HANDLE_VALUE) {
// Handle the error.
log("Failed to create hCom handle");
return false;
}
DWORD lptEvtMask;
fSuccess = GetCommMask(hCom, &lptEvtMask);
if (!fSuccess) {
log("GetCommMask failed");
CloseHandle(hCom);
return false;
}
fSuccess = SetCommMask(hCom, lptEvtMask);
printAll(&lptEvtMask);
// Initialize the DCB structure.
DCB dcb;
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
// Build on the current configuration by first retrieving all current
// settings.
/*fSuccess = GetCommState(hCom, &dcb);
if (!fSuccess) {
log("GetCommState failed");
CloseHandle(hCom);
return false;
}
*/
dcb.BaudRate = readComArg.baudRate; // 115200 baud rate
dcb.ByteSize = readComArg.dataBits; // 8 data size, xmit and rcv
/*
dcb.Parity = readComArg.parity; // parity bit
dcb.StopBits = readComArg.stopBits; // stop bit
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
*/
fSuccess = SetCommState(hCom, &dcb);
if (!fSuccess) {
log("SetCommState failed");
CloseHandle(hCom);
return false;
}
// Get the comm config again.
fSuccess = GetCommState(hCom, &dcb);
if (!fSuccess) {
log("GetCommState failed");
CloseHandle(hCom);
return false;
}
log("Serial Port successfully reconfigured");
hFile = CreateFileW(fileName, // name of the write
FILE_APPEND_DATA, // open for appending
0, // no sharing
NULL, // default security
OPEN_ALWAYS, // open existing file or create new file
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == NULL) {
log("Failed to create hFile handle");
CloseHandle(hCom);
return false;
}
PostMessage(readComArg.MainWindow, WM_THREAD_UP, 0, 0);
return true;
}
Putty doesn't touch any of the DCB fields except DCBlength, BaudRate, ByteSize, Parity, and StopBits, and setting the fields that aren't these five to arbitrary values doesn't seem to affect the code's behavior, so I left the rest at zero.
Here is the main loop code:
void loop(struct ReadComArg readComArg) {
//TODO: close all handles when function returns
const unsigned long BUFFSIZE = 256;
BYTE buffer[BUFFSIZE];
DWORD bytesRead, bytesWritten, result;
OVERLAPPED osReader;
OVERLAPPED osWriter;
HANDLE eventArray[4];
eventArray[0] = readComArg.killEvent;
eventArray[2] = readComArg.writeRequestEvent;
BOOL continueLooping = true;
BOOL fWaitingOnRead = FALSE;
BOOL fWaitingOnWrite = FALSE;
while (continueLooping) {
//There is no outstanding read request and we must create a new one:
if (!fWaitingOnRead) {
//First, check to make sure we haven't received a killEvent.
result = WaitForSingleObject(readComArg.killEvent, 0); //returns immediately
if (result == WAIT_OBJECT_0) {
//received killEvent, exiting
log("killEvent was signaled. Exiting loop");
if (!ResetEvent(readComArg.killEvent))
log("failed to reset killEvent");
break;
}
else if (result != WAIT_TIMEOUT) {
//some error occured
log("WaitForSingleObject returned an error");
break;
}
//Otherwise, there was no kill request, continue as normal.
//Attempt to create new read request
osReader = { 0 };
osReader.hEvent = CreateEvent(NULL, true, false, NULL);
//read event failed to allocate, return:
if (osReader.hEvent == NULL) {
log("failed to create readEvent");
break;
}
eventArray[1] = osReader.hEvent;
//Execute the asynchronous read:
if (!ReadFile(hCom, buffer, BUFFSIZE, &bytesRead, &osReader)) {
//The asynchronous read request succeeded and will be completed later:
if (GetLastError() == ERROR_IO_PENDING) {
log("Read request queued and pending");
fWaitingOnRead = TRUE;
}
//The asynchronous read request failed:
else {
log("ReadFile returned an error");
CloseHandle(osReader.hEvent);
break;
}
}
//The asynchronous read request succeeded and completed immediately:
else {
log("Read request queued and returned immediately");
CloseHandle(osReader.hEvent);
handleRead(readComArg, buffer, bytesRead);
}
}
//We are waiting on an outstanding read request:
else {
//block until a signal arrives
//if we are waiting on a write, then there is an additional signal we must block for
if (fWaitingOnWrite) {
log("blocking for kills, reads, writeRequests, and writeResponses.");
result = WaitForMultipleObjects(4, eventArray, FALSE, INFINITE);
}
else {
log("blocking for kills, reads, and writeRequests. No outstanding write Request.");
result = WaitForMultipleObjects(3, eventArray, FALSE, INFINITE);
}
continueLooping = false;
switch (result) {
//The killEvent handle received a signal. This has priority over every other signal.
case WAIT_OBJECT_0:
log("Received killEvent. Exiting loop");
if (!ResetEvent(readComArg.killEvent))
log("failed to reset killEvent");
break;
//The com port handle received a signal
case WAIT_OBJECT_0+1:
log("received signal");
//Unsuccessful read
if (!GetOverlappedResult(hCom, &osReader, &bytesRead, FALSE)) {
log("GetOverlappedResult returned an error");
break;
}
//Successful read, continue looping
log("Outstanding read request fulfilled");
handleRead(readComArg, buffer, bytesRead);
fWaitingOnRead = FALSE;
CloseHandle(osReader.hEvent);
continueLooping = true;
break;
//The writeRequestEvent handle received a signal. Create an asynchronous write request:
case WAIT_OBJECT_0 + 2:
//reset writeRequestEvent signal.
if (!ResetEvent(readComArg.writeRequestEvent)) {
log("failed to reset writeRequestEvent");
break;
}
//attempt to create writeResponseEvent:
osWriter = { 0 };
osWriter.hEvent = CreateEvent(NULL, true, false, NULL);
if (osWriter.hEvent == NULL) {
log("failed to create writeResponseEvent");
break;
}
eventArray[3] = osWriter.hEvent;
//execute the asynchronous write:
if (!WriteFile(hCom, readComArg.writeBuffer, readComArg.numCharsToWrite, &bytesWritten, &osWriter)) {
//The asynchronous write request succeeded and will be completed later:
if (GetLastError() == ERROR_IO_PENDING) {
log("Write request queued and pending");
fWaitingOnWrite = true;
continueLooping = true;
break;
}
//The asynchronous write request failed:
else {
log("WriteFile returned an error");
CloseHandle(osWriter.hEvent);
break;
}
}
//The asynchronous write request succeeded and completed immediately
else {
log("Write request queued and returned immediately");
CloseHandle(osWriter.hEvent);
continueLooping = true;
PostMessage(readComArg.MainWindow, WM_THREAD_SENT, 0, 0);
break;
}
break;
//The writeResponseEvent handle received a signal
case WAIT_OBJECT_0+3:
//Unsuccessful write
if (!GetOverlappedResult(hCom, &osWriter, &bytesWritten, FALSE)) {
log("GetOverlappedResult returned an error");
break;
}
//Successful write, continue looping
PostMessage(readComArg.MainWindow, WM_THREAD_SENT, 0, 0);
log("Outstanding write request fulfilled");
fWaitingOnWrite = FALSE;
CloseHandle(osWriter.hEvent);
continueLooping = true;
break;
// Error in WaitForMultipleObjects()
default:
log("WaitForMultipleObjects returned an error");
break;
}
}
}
CancelIo(hCom);
if(fWaitingOnRead)
CloseHandle(osReader.hEvent);
if (fWaitingOnWrite)
CloseHandle(osWriter.hEvent);
}
I am not very familiar with StackOverflow ettiquette, so if there is something incorrect with how I am asking my question, I apologize in advance and will correct it as soon as I am able. Thank you.
I am running this g_test where I simply initialize and close a client.
TEST(safIpc, createAndCloseClient)
{
std::shared_ptr<fnv::ipcsvc::IpcSvc> safIpc = std::make_shared<fnv::ipcsvc::IpcSvc>();
const std::string& app1 {"/testApp1"};
const std::string& groupName {"wir_clients"};
fnv::ipcsvc::IpcSvcAttrMq attr(fnv::ipcsvc::IpcSvcAttrType::MQ_CLIENT,
app1,
groupName,
"/server");
std::shared_ptr<IpcSvcTestSafHandler> msgHandler = std::make_shared<IpcSvcTestSafHandler>();
// initialize the ipc library
IpcSvcPriv::SharedPtr ipcPrivData {nullptr};
fnv::ipcsvc::IpcSvcRet ret = safIpc->init(attr, msgHandler, ipcPrivData);
EXPECT_EQ(ret, fnv::ipcsvc::IpcSvcRet::SUCCESS);
EXPECT_NE(ipcPrivData, nullptr);
ret = safIpc->close(ipcPrivData, app1); //HANGS here
EXPECT_EQ(fnv::ipcsvc::IpcSvcRet::SUCCESS, ret);
}
In init I create 3 threads: (here is the relevant part of the init code):
1- A process thread
2- a Receive thread
3- A timer thread
int rc = pthread_create(&m_timerThread,
NULL,
&IpcSvcImpl::timer_start,
this);
if (rc != 0)
{
ipcSvcLog(LOGE, "Failed to create timer thread!");
close(tmpPrivData,
attr.getAppId());
return error;
}
pthread_setname_np(m_timerThread,
"IpcSvcTimerThread");
}
// Start the worker threads
int rc = pthread_create(&m_receiveThread,
NULL,
&IpcSvcImpl::receive,
this);
if (rc != 0)
{
//TODO some error log
close(tmpPrivData,
attr.getAppId());
return error;
}
pthread_setname_np(m_receiveThread,
"IpcSvcReceiveThread");
rc = pthread_create(&m_processThread,
NULL,
&IpcSvcImpl::process,
this);
if (rc != 0)
{
//TODO some error log
close(tmpPrivData,
attr.getAppId());
return error;
}
pthread_setname_np(m_processThread,
"IpcSvcProcessThread");
Here is the close function:
IpcSvcRet IpcSvcImpl::close(IpcSvcPriv::SharedPtr privateData,
const std::string& appId)
{
if (!privateData)
{
//TODO log about client not providing sane private data
return IpcSvcRet::FAIL;
}
// acquire the mutex and set close called to true
{
std::lock_guard<std::mutex> guard(m_closeMtx);
m_closed = true;
}
if (m_msgQueue)
{
m_msgQueue->mutexInit();
// writing dummy message to process thread
std::pair<std::array<uint8_t, IPCSVC_MAX_MSG_SIZE>, ssize_t> queueMsg;
m_msgQueue->enqueue(queueMsg);
}
// writing dummy message to receive thread
uint32_t buffer = 0;
sendData(privateData,
(void*)&buffer,
sizeof(uint32_t),
appId);
pthread_join(m_receiveThread,
NULL);
pthread_join(m_processThread,
NULL);
if (m_isClient)
{
m_cv.notify_one();
printf("timer thread hangs\n"); // HANGS HERE ///////////////////////////////////////
pthread_join(m_timerThread,
NULL);
//This line is never reached..
}
delete m_msgQueue;
m_msgQueue = nullptr;
// close the ipc layer
if (m_ipc)
{
m_ipc->close();
delete m_ipc;
m_ipc = nullptr;
}
m_clientsList.clear();
m_hbManager = { };
return IpcSvcRet::SUCCESS;
}
Here is the timer_start function:
The timer thread is a timer that is keeps looping forever unless the fc->m_closed is set to true. It triggers fc->timerExpiry() every 2 seconds.
// timer thread entry
void* IpcSvcImpl::timer_start(void *arg)
{
if (!arg)
{
return nullptr;
}
printf("starting timer\n");
IpcSvcImpl* fc = static_cast<IpcSvcImpl *>(arg);
std::unique_lock<std::mutex> lock(fc->m_closeMtx);
while (!(fc->m_closed))
{
printf("Entering loop\n");
lock.unlock();
auto expireAt = std::chrono::steady_clock::now() +
std::chrono::seconds(fc->getTimerInterval());
fc->timerExpiry();
lock.lock();
printf("here?\n");
fc->m_cv.wait_until(lock, expireAt);
printf("Here 2\n");
}
printf("Exited loop\n\n");
return nullptr;
}
The output of the unittest:
[----------] 5 tests from safIpc
[ RUN ] safIpc.createAndCloseClient
starting timer
Entering loop
closing..
timer thread hangs
pthread join hangs forever, I am not sure why. The "here" prints are never hit, which seems odd.
Thanks for the help!
i build Simple Anticheat module for a game and i need protect the Thread's from a Suspend (Like Suspend Thread from Processhacker).
Is there any way to automatically resume the thread if is suspended?
Here is my module code:
#include "stdafx.h"
#include "Start.h"
void Msg_Sf_Br(){
MessageBoxA(NULL,"SpeedHack - Detect", load.Nome_das_Janelas, MB_SERVICE_NOTIFICATION | MB_ICONWARNING);
ExitProcess(0);
}
void Msg_Sf_En(){
MessageBoxA(NULL,"SpeedHack - Detect", load.Nome_das_Janelas, MB_SERVICE_NOTIFICATION | MB_ICONWARNING);
ExitProcess(0);
}
void Speed_perf()
{
if( *(unsigned long*)QueryPerformanceCounter != 2337669003 ){
if (load.Log_Txt_Hack == 1){
}
if (load.Message_Warning_En == 1){
ExitProcess(0);
}
if (load.Message_Warning_En == 2){
CreateThread(NULL,NULL,LPTHREAD_START_ROUTINE(Msg_Sf_Br),NULL,0,0);
Sleep(3000);
ExitProcess(0);
}
if (load.Message_Warning_En == 0){
ExitProcess(0);
}
else
ExitProcess(0);
}
}
void performance(){
if (load.Anti_Kill_Scans == 1)
{
again:
Speed_perf();
Sleep(load.Detecta_Speed_PerformanceT);
goto again;
}
else
{
again2:
Speed_perf();
Sleep(load.Detecta_Speed_PerformanceT);
goto again2;
}
}
void SPerformance(){
CreateThread(NULL,NULL,LPTHREAD_START_ROUTINE(performance),NULL,0,0);
}
Any idea?
With a little trick you can hide your thread from any debugger or tools like process hacker.
void func()
{
}
int main()
{
int(__stdcall* ZwCreateThreadEx)(HANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, HANDLE, PVOID, PVOID, ULONG, ULONG_PTR, SIZE_T, SIZE_T, PVOID) = (decltype(ZwCreateThreadEx))GetProcAddress(GetModuleHandle("ntdll.dll"),"ZwCreateThreadEx");
HANDLE hThread=0;
ZwCreateThreadEx(&hThread,0x1FFFFF,0,GetCurrentProcess(),
(LPTHREAD_START_ROUTINE)func,0, 0x4/*hide flag*/,0,0x1000,0x10000,0);
return 0;
}
You can do it this way:
get list of process thread ids, using CreateToolhelp32Snapshot
go to first thread using methods: Thread32First.
for each found thread (you should check if belong to the given process):
then Open the thread using OpenThread in manner to retrieve handle to the thread from it thread id,
when you have the handle, you can suspend the thread using SuspendThread in manner to retrieve the previous suspension count,
then you can Resume the thread until it suspension count is 0. you must resume at least once in manner to cancel the suspension from the previous step.
if thread are not allowed to be suspended, you can use ResumeThread just to get the suspension count even if it was not suspended.
Close the thread handle using CloseHandle
iterate to next thread use Thread32Next.
In manner to be able to do the whole thing you must run as administrator.
Here is an example:
void TraverseProcessThreads(DWORD pid)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); //get list of all system thread
if( hSnapshot == INVALID_HANDLE_VALUE)
{
//print error and return;
return;
}
THREADENTRY32 threadEntry;
if( Thread32First( hSnapshot, &threadEntry) )
{
size_t threadsCounter = 0, suspendedThreadsCounter=0;
do{
if(te.th32OwnerProcessID == pid) //we get all threads in system, should filter the relevant pid.
{
threadsCounter ++; //found thread
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,FALSE,te.th32ThreadID); //get handle to thread from its thread id
if(hThread == NULL) //
{
//print error and break. (will be permission error if not administrator)
break;
}
int suspensionCount = SuspendThread( hThread ) ;//will return previous suspension count. you can also use ResumeThread if there's no way it can be suspended.
if(suspensionCount > 0)
{
//thread was suspended
suspendedThreadsCounter ++;
}
//cancel our suspension...
suspensionCount = ResumeThread(hThread );
/*to resume suspended thread use ResumeThread until it return 1.
do{
suspensionCount = ResumeThread(hThread );
}while (suspensionCount > 1); //similar to Suspend Resume return previous Suspention count.
*/
}
CloseHandle(hThread);
}while(Thread32Next( hSnapshot, &threadEntry) );
//print results:
cout<<"process id"<<pid<<endl<<" has "<<threadsCounter <<" threads " <<endl
<<suspendedThreadsCounter <<" threads was suspended"<<endl;
}
else{
//print some error...
}
CloseHandle(hSnapshot);
}
The function WaitForSingleObject returns timeout flag("WAIT_OBJECT_0") in all cases.
Only for testing I have commented this line
(while((WaitForSingleObject(ovread.hEvent,timeout)==WAIT_OBJECT_0)))
and the comport responds as expected.
I have tried various timeouts including INFINITE.
Can someone tell me where the error could be occurring.
int timeout=500;
OVERLAPPED ovread;
memset(&ovread, 0, sizeof(ovread));
ovread.hEvent = CreateEvent( 0,true,0,0);
while((WaitForSingleObject(ovread.hEvent,timeout)==WAIT_OBJECT_0))
{
//Execute the following code
ReadFile(h,buf,sizeof(buf),&read,&ovread);
}
The reading logic should more or less use the following code flow:
int timeout = 500;
OVERLAPPED ovread = {0}
ovread.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ovread.hEvent == NULL) {
// Error creating overlapped event; abort.
return FALSE;
}
if (!ReadFile(h, buf, sizeof(buf), &read, &ovread)) {
if (GetLastError() != ERROR_IO_PENDING) {
// Handle error in communications
}
else {
DWORD ret = WaitForSingleObject(ovread.hEvent,timeout);
switch (ret) {
case WAIT_OBJECT_0:
HandleASuccessfulRead(buf, read);
break;
case WAIT_TIMEOUT:
// Handle timeout
break;
case WAIT_FAILED:
// Handle failure
break;
default:
// what else to handle?
break;
}
}
}
else {
// read completed immediately
HandleASuccessfulRead(buf, read);
}