How to handle with return number given by lua_resume? - lua

I have some coroutine handling code like this:
int coro_re_num = 0;
int coro_state = lua_resume( coro_lua, master_lua, narg, &coro_re_num);
if ( coro_state == LUA_OK)
{
// do something
}
else if ( coro_state == LUA_YIELD)
{
// do_something
}
else
{
const char* err = lua_tostring(coro_lua, -1);
log_error(err);
}
lua_pop(master_lua, coro_re_num);
When coroutine ends with OK or YIELD, it works properly. But when it ends with any error, the last lua_pop always fail, and I noticed the coro_re_num is relatively large (mostly more than 10) which causes stack underflow by lua_pop.
What does the coro_re_num means when the coroutine ends with error? How to handle it?

Related

Lua yielding across C-call boundary

I'm trying to call lua_yield inside a debug hook, and get this error in my output. I'm wanting to yield after a certain number of instructions have been processed and was hoping this was the way to do it.
I'm writing this using some Python ctypes bindings.
yielding
b'test.lua:1: attempt to yield across C-call boundary'
I assumed this should work since I'm using LuaJIT and it has a fully resumable VM.
#lua_Hook
def l_dbg_count(L: lua_State_p, ar: ctypes.POINTER(lua_Debug)):
if ar.contents.event == EventCode.HookCount:
print("yielding")
lua_yield(L, 0)
#main method
def main():
...
lua_sethook(L, l_dbg_count, DebugEventMask.Count, 1)
luaL_loadfile(L, b"test.lua")
ret = lua_pcall(L, 0, 0, 0)
while True:
if ret != LuaError.Ok and ret != LuaError.Yield:
print(lua_tostring(L, -1))
break
elif ret == LuaError.Yield:
print("resuming")
ret = lua_resume(L, None, 0)
lua_close(L)
I first must push a new thread using lua_newthread, then calling luaL_loadfile and instead of lua_pcall, calling lua_resume.
I rewrote this in C to check if there was possible stack unwinding issues from Lua to Python.
void l_dbg_count(lua_State *L, lua_Debug *ar) {
if(ar->event == LUA_HOOKCOUNT) {
printf("yielding\n");
lua_yield(L, 0);
}
}
...
int main(int argc, char **argv) {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_sethook(L, l_dbg_count, LUA_MASKCOUNT, 5);
lua_State *L_t = lua_newthread(L);
luaL_loadfile(L_t, "test.lua");
int ret = lua_resume(L_t, 0);
while(true) {
if(ret != 0 && ret != LUA_YIELD) {
fprintf(stderr, "%s", lua_tostring(L_t, -1));
break;
} else if(ret == LUA_YIELD) {
printf("resuming\n");
ret = lua_resume(L_t, 0);
} else {
break;
}
}
lua_close(L);
return EXIT_SUCCESS;
}
This however does break the coroutine library from working it seems, so currently looking into a possible fix for that.

crash while reading the socket data - recv() - in objective-c

I'm trying to read data from the socket and it works fine most of the time.
When I run the app for longer duration - app crashes and crashlytics points the crash to readingSocket() - this function just reads raw data from socket.
Below is code of readingSocket()
-(bool) readingSocket:(NSMutableData*)dataIn readBytes:(ssize_t)quantity error:(NSError **)error {
ssize_t readBytesNow = 0;
ssize_t grossRead= 0;
[dataIn setLength:0];
if (error != nil) {
*error = nil;
}
char *buffer = new char[6144];
do {
ssize_t readBytes = (quantity - grossRead);
readBytesNow = recv((int)raw_Socket, buffer, readBytes , MSG_DONTWAIT);
if (readBytesNow == 0) {
NSLog(#" read error");
delete[] buffer;
return false;
}
Else if (bytesRead < 0) {
if (errno == EAGAIN) {
[NSThread sleepForTimeInterval:0.5f];
NSLog(#" EAGAIN error");
continue;
}
else {
// if error != nil
delete[] buffer;
return false;
}
}
else if (readBytesNow > 0) {
grossRead += readBytesNow;
// doing some operations
}
} while (grossRead < quantity);
delete[] buffer;
return true;
}
I'm already doing so many checks after reading but not sure where could the probable cause for the crash or exception ??
any other better way to handle exception in my above code ?
I can't comment without 50 reputation (new user here), so here goes my comment as an answer.
Warning: I have no idea of the language your code is written, but I'm using my instincts as a C++ programmer (and probably mediocre one at it).
First thing I noticed was this piece of code:
if (error != nil) {
*error = nil;
}
In C world, this would be similar to checking if a pointer is null, but assigning null as its value afterwards.
Second thing to note is this construct:
-(bool) readingSocket:(NSMutableData*)dataIn readBytes:(ssize_t)quantity error:(NSError **)error {
...
char *buffer = new char[6144];
...
ssize_t readBytes = (quantity - grossRead);
When quantity > 6144 i.e. once in a blue moon, your network stack might read more than 6144 bytes which would result in a buffer overflow.
Tangential comments:
1) I think you should note that EAGAIN and EWOULDBLOCK may be the same value but not guaranteed. You might consider checking for both of them if you are not certain that your platform behaves exactly as you think.
An example link to Linux documentation
2) Your logic,
if (readBytesNow == 0) {
...
} Else if (bytesRead < 0) {
...
} else if (readBytesNow > 0) {
...
}
although being verbose, is unnecessary. You can use
if (readBytesNow == 0) {
...
} Else if (bytesRead < 0) {
...
} else {
...
}
to be sure you are not getting an additional comparison. This comparison might get optimised out anyway, but writing this way makes more sense. I had to look again to see "if I am missing something".
Hope these help.

pthread_Join can't return after call pthread_cancel?

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()).

Bad file descriptor on pthread_detach

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.

Problem with wsarecv while using with IOCP

I am new to IOCP and struggling with this for last few weeks.
I have pasted some core part of my code below related to IOCP.This may not be executed perfectly as I clipped some part to make it easy to understand.
I am struggling while receiving the data.As it comes to wsarecv in worket thread, wsarecv returns WSA_IO_PENDING error code so I call WSAGetOverlappedResult to check operation to be completed.
Twist comes here, rather it proceed and call my local function ProcessTelegramData after WSAGetOverlappedResult , same part of code(wsarecv called again) is executed again by another worker thread which try to call ProcessTelegramData and buffer value is invalid in it.
I am unable to understand
why another thread calling wsarecv again when WSAGetOverlappedResult is called and
why buffer value is getting invalidated?
unsigned LicTCPServer::WorkerThread(LPVOID lpParam)
{
//int nThreadNo = (int)lpParam;
LicTCPServer* pThis = reinterpret_cast<LicTCPServer*>(lpParam);
void *lpContext = NULL;
OVERLAPPED *pOverlapped = NULL;
CClientContext *pClientContext = NULL;
DWORD dwBytesTransfered = 0;
int nBytesRecv = 0;
int nBytesSent = 0;
DWORD dwBytes = 0, dwFlags = 0;
//Worker thread will be around to process requests, until a Shutdown event is not Signaled.
while (WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
{
BOOL bReturn = GetQueuedCompletionStatus(
g_hIOCompletionPort,
&dwBytesTransfered,
(LPDWORD)&lpContext,
&pOverlapped,
INFINITE);
if (NULL == lpContext)
{
//We are shutting down
break;
}
//Get the client context
pClientContext = (CClientContext *)lpContext;
if ((FALSE == bReturn) /*|| ((TRUE == bReturn) && (0 == dwBytesTransfered))*/)
{
//Client connection gone, remove it.
pThis->RemoveFromClientListAndFreeMemory(pClientContext);
continue;
}
WSABUF *p_wbuf = pClientContext->GetWSABUFPtr();
OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr();
//printf("reached %d\n",pClientContext->GetOpCode());
printf("Get Queued received\n");
switch (pClientContext->GetOpCode())
{
case OP_READ:
{
//Once the data is successfully received, we will print it.
//pClientContext->SetOpCode(OP_WRITE);
pClientContext->ResetWSABUF();
dwFlags = 0;
//int a = recv(pClientContext->GetSocket(), p_wbuf->buf, p_wbuf->len, 0);
//Get the data.
if(WSARecv(pClientContext->GetSocket(), p_wbuf, 1, &dwBytes, &dwFlags, p_ol, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf("Error occured at WSARecv()\n");
return 0;
}
}
DWORD byteTr = 0;
WSAGetOverlappedResult(pClientContext->GetSocket(),p_ol,&byteTr,TRUE,&dwFlags);
if( byteTr > 0 )
{
//doing some operatin on data received
printf("Process tele called\n");
g_pLicServFunc->ProcessTelegramData(pClientContext->GetSocket(), p_wbuf->buf, byteTr);
}
if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSARecv().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
}
break;
case OP_WRITE:
char szBuffer[MAX_BUFFER_LEN];
//Send the message back to the client.
pClientContext->SetOpCode(OP_READ);
pClientContext->SetTotalBytes(dwBytesTransfered);
pClientContext->SetSentBytes(0);
//p_wbuf->len = dwBytesTransfered;
dwFlags = 0;
DWORD temp;
//Overlapped send
printf("reached Going to send\n");
//send(pClientContext->GetSocket(), p_wbuf->buf,p_wbuf->len, 0);
nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1,
&temp, dwFlags, p_ol, NULL);
if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSASend().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
break;
default:
printf("reached to default\n");
//We should never be reaching here, under normal circumstances.
break;
} // switch
} // while
return 0;
}
I had a similar issue with WSARecv where it always queued to the io completion queue, even if it succeeded immediately. I had to ignore a return value indicating success and instead handle the queued result that I got from GetQueuedCompletionStatus.

Resources