pselect problems with FD_ISSET on cygwin - sockets

I'm running cygwin and use pselect to monitor a socket and filedescriptors for child processes.
According to some example that I found here http://www.linuxprogrammingblog.com/code-examples/using-pselect-to-avoid-a-signal-race and the man pages pselect should return the number of filedescriptors which are set in the mask fields (http://linux.die.net/man/2/pselect).
Now when I connect to my server pselect returns, which is fine. But when I test for the filedescriptors using FD_ISSET they always return true:
FD_ZERO(&readers);
FD_ZERO(&writers);
FD_ZERO(&exceptions);
FD_SET(fileno(stdin), &readers);
FD_SET(socket, &readers);
pret = pselect(FD_SETSIZE, &readers, &writers, &exceptions, NULL, &mSignalMask);
, &readers, &writers, &exceptions, NULL, &mSignalMask);
if(pret <= 0)
{
// ignore for now
continue;
}
if(FD_ISSET(fileno(stdin), &readers))
{
string s;
cin >> s;
cout << "stdin: " << s << endl; // blocks because the code always gets here even when
// pselect returns because of a childsignal without any data.
continue;
}
if(FD_ISSET(socket, &readers))
{
accept(); // blocks because the code always gets here even when
// pselect returns because of a childsignal without any data.
cout << "task created connection from " <<task->getClientHost() << endl;
continue;
}

Found the problem myself. FD_ISSET can ONLY be used if the result from pselect is > 0, otherweise the returnvalue from FD_ISSET is as before the call. So best treat it as undefined when pselect returns <= 0;

Related

Questions about select()

Considering the following class method:
void TCPServer::listenWithTimeout() {
fd_set descrSet;
struct timeval timeout = {1, 0};
while (listeningThread.active) {
std::cout << "TCP Server thread is listening..." << std::endl;
FD_ZERO(&descrSet);
FD_SET(mySocketFD, &descrSet);
int descrAmount = select(mySocketFD + 1, &descrSet, NULL, NULL, &timeout);
if (descrAmount > 0) {
assert(FD_ISSET(mySocketFD, &descrSet));
int threadIndx = findAvailableThread();
if (threadIndx < 0) {
std::cout << "Connection not accepted: no threads available..." << std::endl;
} else {
joinThread(threadIndx);
int newSocketFD = accept(mySocketFD, (struct sockaddr *) &mySocket, &clieAddrssLen);
std::cout << "TCP Client connected..." << std::endl;
connectionThreads[threadIndx].thread = std::thread(TCPServer::startTCPConnectionWithException, std::ref(*this), threadIndx, newSocketFD);
connectionThreads[threadIndx].active = true;
}
}
}
std::cout << "TCP Server thread is terminating..." << std::endl;
}
Here are some question:
when there are not available threads (findAvailableThreads() returns -1), is it a normal behaviour that select() doesn't wait its timeout and so the while loop iterates really fast until a new thread is available?
if yes, how could I avoid these really fast iterations? Instead of using something like a simple sleep() at line 13 inside the if branch, is there a way to let select() restore its timeout? Or even, is there a way to completely reject the incoming connection pending?
when there are not available threads (findAvailableThreads() returns -1), is it a normal behaviour that select() doesn't wait its timeout and so the while loop iterates really fast until a new thread is available?
Yes, because under that condition, you are not calling accept(), so you are not changing the listening socket's state. It will remain in a readable state as long as it has a client connection waiting to be accept()'ed.
if yes, how could I avoid these really fast iterations?
Call accept() before checking for an available thread. If no thread is available, close the accepted connection.
Instead of using something like a simple sleep() at line 13, inside the if branch, is there a way to let select() restore its timeout?
The only way is to accept() the connection that put the listening socket into a readable state, so it has a chance to go back to a non-readable state. The timeout will not apply again until the socket is no longer in a readable state.
Or even, is there a way to completely reject the incoming connection pending?
The only way is to accept() it first, then you can close() it if needed.
Try this:
void TCPServer::listenWithTimeout() {
fd_set descrSet;
while (listeningThread.active) {
std::cout << "TCP Server thread is listening..." << std::endl;
FD_ZERO(&descrSet);
FD_SET(mySocketFD, &descrSet);
struct timeval timeout = {1, 0};
int descrAmount = select(mySocketFD + 1, &descrSet, NULL, NULL, &timeout);
if (descrAmount > 0) {
assert(FD_ISSET(mySocketFD, &descrSet));
int newSocketFD = accept(mySocketFD, (struct sockaddr *) &mySocket, &clieAddrssLen);
if (newSocketFD != -1) {
int threadIndx = findAvailableThread();
if (threadIndx < 0) {
close(newSocketFD);
std::cout << "Connection not accepted: no threads available..." << std::endl;
} else {
joinThread(threadIndx);
std::cout << "TCP Client connected..." << std::endl;
connectionThreads[threadIndx].thread = std::thread(TCPServer::startTCPConnectionWithException, std::ref(*this), threadIndx, newSocketFD);
connectionThreads[threadIndx].active = true;
}
}
}
}
std::cout << "TCP Server thread is terminating..." << std::endl;
}

Why is the code failing in the Destructor?

I have gone through stackoverflow questions similar to "Why is the destructor called twice?". My question can be a similar one but with a small change. I am getting an error when running the following code:
struct Employee{
char *name;
char *tag;
Employee *employee;
Employee(){
name = NULL;
tag = NULL;
employee = NULL;
}
//copy constructor
Employee(const Employee &obj){
cout << "Copy constructor called" << endl;
name = (char*)malloc(sizeof(char)*strlen(obj.name));
strcpy(name, obj.name);
tag = (char*)malloc(sizeof(char)*strlen(obj.tag));
strcpy(tag, obj.tag);
employee = (struct Employee*)malloc(sizeof(obj.employee));
employee = obj.employee;
}
//overloaded assignment operator
void operator = (const Employee &obj){
cout << "Assignment operator called" << endl;
if (this == &obj){
return;
}
strcpy(name, obj.name);
strcpy(tag, obj.tag);
employee = obj.employee;
}
//destructor
~Employee(){
cout << "Destructor called" << endl;
if (name != NULL){
cout << "Freeing name" << endl;
free(name);
name = NULL;
}
if (tag != NULL){
cout << "Freeing tag" << endl;
free(tag);
tag = NULL;
}
if (employee != NULL){
cout << "Freeing employee" << endl;
free(employee);
employee = NULL;
}
}
};
Employee createNode(){
Employee emp;
emp.name = (char*)malloc(sizeof(char)* 25);
strcpy(emp.name, "Alan");
emp.tag = (char*)malloc(sizeof(char)* 25);
strcpy(emp.tag, "Engineer");
emp.employee = (struct Employee*)malloc(sizeof(struct Employee));//just created memory, no initialization
return emp;
}
Employee get(){
//Employee emp = createNode();
//return emp;
return createNode();
}
int main(){
Employee emp = get();
getchar();
return 0;
}
I debugged the code and found that error is raising when the destructor is called second time when the main function exits.
1) I want to know why the code fails to run?
2) Are there any memory leaks?
3) How can I fix the error properly deallocating memory?
Thanks in advance.
Update:
As per the three Rule I have also added a copy constructor and overloaded the assignment operator. But the error(Expression : _crtisvalidheappointer(puserdata)) is raising. After checking in the Google I could see that some where the Heap corruption is happening. When I comment the initialization of the Struct member employee in the createNode() then I could see the error raising when trying to free the employee in destructor. So I suspect the problem is with the employee struct member. Please help me with this.I am using Visual studio for debugging and running.
Your problem is a lack of copy construct and assignment operator in your class. As a result you are freeing the strings within the class multiple times.
Just tried your code and found out a few issues that causes a crash:
1) strlen returns length of string without null terminator character, but strcpy requires that additional byte, so your allocating should look like that:
name = (char*)malloc(strlen(obj.name)+1);
2) When you copy employee, you copy pointer, so you have memory leak and employee pointer as a dangling one.
Also malloc cannot work with constructors, therefore after
employee = (struct Employee*)malloc(sizeof(obj.employee));
employee has a garbage inside.

Flex and Lemon Parser

I'm trying to learn flex and lemon, in order to parse a (moderately) complex file format. So far, I have my grammar and lex file and I believe it is correctly parsing an example file. Right now, I want to pass the token text scanned with flex to lemon.
The flex YYSTYPE is defined as
#define YYSTYPE char*
The lemon token type is
%token_type {char *}
However, if I have a set of rules in lemon:
start ::= MATDEF IDENTIFIER(matName) LEFT_CURLY_BRACE(left) materialDefinitionBody(mBody) RIGHT_CURLY_BRACE(right) .
{
std::string r = std::string(matName) + std::string(left) + mBody + std::string(right);
std::cout << "result " << r << std::endl;
}
materialDefinitionBody(r) ::= techniqueList .
{
r = "a";
}
the output will be
result a
when it should be something like
mat1 { a }
My main parsing loop is:
void parse(const string& commandLine) {
// Set up the scanner
yyscan_t scanner;
yylex_init(&scanner);
YY_BUFFER_STATE bufferState = yy_scan_string(commandLine.c_str(), scanner);
// Set up the parser
void* shellParser = ParseAlloc(malloc);
yylval = new char[512];
int lexCode;
do {
yylval[0] = 0;
lexCode = yylex(scanner);
cout << lexCode << " : " << yylval << std::endl;
Parse(shellParser, lexCode, yylval);
}
while (lexCode > 0);
if (-1 == lexCode) {
cerr << "The scanner encountered an error.\n";
}
// Cleanup the scanner and parser
yy_delete_buffer(bufferState, scanner);
yylex_destroy(scanner);
ParseFree(shellParser, free);
}
The cout line is printing the correct lexCode/yylval combination.
What is the best way? I can't find anything that works.
You need to have
yylval = new char[512];
inside the do-while loop.

Select c: wfds is always turned on, causing block

For some reason FD_ISSET always returns true for &wfds, even when there is nothing to send. Here is the code snippet (same on both client and server). Both client and server get same issue with select saying wfds is on. Shouldn't it only activate when i type a message on my keyboard and press enter?
while (1) {
//trying select..
tv.tv_sec = 29;
tv.tv_usec = 500000;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(new_sockfd, &rfds);
FD_SET(new_sockfd, &wfds);
n = select(new_sockfd + 1, &rfds, &wfds, NULL, &tv);
if (n > 0) {
if (FD_ISSET(new_sockfd, &rfds)) {
while (1) {
if ((num = recv(new_sockfd, buffer, 10240, 0)) == -1) {
//fprintf(stderr,"Error in receiving message!!\n");
perror("recv");
exit(1);
} else if (num == 0) {
printf("Connection closed\n");
return 0;
}
buffer[num] = '\0';
printf("Message received: %s\n", buffer);
break;
}
}
//this always returns true on client and host
if (FD_ISSET(new_sockfd, &wfds)) {
while (1) {
fgets(buffer, MAXDATASIZE - 1, stdin);
if ((send(new_sockfd, buffer, strlen(buffer), 0)) == -1) {
fprintf(stderr, "Failure Sending Message\n");
close(new_sockfd);
exit(1);
} else {
printf("Message being sent: %s\n", buffer);
break;
}
}
}
}
}
You probably misunderstood how writefds parameter works for select().
You should set the flag in writefds for your file descriptor before calling select() if and only if you have something to send.
Then select() returns with the flag left set in writefds, when the socket has enough space in the socket buffers to accept data for sending. Then you check for that flag, and realize that the socket is available for sending, and you also know that you have something to send, since originally it was you, who set the flag before calling select(). Therefore you can proceed with sending the data over the socket. Then, if you have sent all data you have, and your to-be-sent buffers are empty, you keep the flag for writefds cleared when next time you call select().

mq_receive: message too long

I am implementing a communication between 2 processes using a queue. The problem is that when I call the function mq_receive, I get this error: Message too long.
I have done the following:
struct mq_attr attr;
long size = attr.mq_msgsize;
.... // initializing the queue "/gateway"
int rc = mq_receive(gateway, buffer, size, &prio);
If I print the size value, I get size=1, while when I print the same size but from another program (got by the same mechanism), I get something not long integer ( -1217186280 )...
How can I solve this error?....so while size = 1, I believe it's right to say "message too long" but why is 1?
P.S. I have also tried to put :
int rc = mq_receive(gateway, buffer, sizeof(buffer), &prio);
but with no result.
It seems like you need to read the docs more carefully. When you call mq_receive you should pass size of the destination buffer. This size must be greater than the mq_msgsize attribute of the queue. In addition, it seems like you have an error in queue attributes initialisation that makes proper mq_receive call impossible. Here is standard message queue session:
Fill mq_attr struct (doc):
struct mq_attr attr;
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = 33;
attr.mq_curmsgs = 0;
Create queue with mq_open in master process (doc):
mqd_t queue = mq_open(qname, O_CREAT|O_RDWR, 0644, &attr);
In writer process open queue for writing:
mqd_t queue = mq_open(qname, O_WRONLY);
And send some text. Length of the text must be lesser than mq_msgsize attribute of the queue (doc):
mq_send(queue, "some message", strlen("some message")+1, 1);
In reader process open queue for reading:
mqd_t queue = mq_open(qname, O_RDONLY);
And then allocate buffer and receive message. Size of buffer *must be greater than the mq_msgsize attribute of the queue. Here we create 50-byte buffer while mq_msgsize == 33 (doc):
char rcvmsg[50];
int iret = mq_receive(queue, rcvmsg, 50, NULL);
Also remember that you should use %ld for print long instead of %d.
When debugging realtime POSIX queues, you should start with a sample program which works and go forward from there. Once you have the sample program running, it should be a simple matter of ensuring that your own code follows all the steps.
The following program has been tested successfully under Ubuntu 11.04:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mqueue.h>
#define MQNAME "/pax"
#define MQMESG "Hello there!"
static mqd_t serverUp (void) {
int rc;
mqd_t svrHndl;
struct mq_attr mqAttr;
printf ("Bringing up server.\n");
rc = mq_unlink (MQNAME);
if (rc < 0) {
printf (" Warning %d (%s) on server mq_unlink.\n",
errno, strerror (errno));
}
mqAttr.mq_maxmsg = 10;
mqAttr.mq_msgsize = 1024;
svrHndl = mq_open (MQNAME, O_RDWR|O_CREAT, S_IWUSR|S_IRUSR, &mqAttr);
if (svrHndl < 0) {
printf (" Error %d (%s) on server mq_open.\n",
errno, strerror (errno));
exit (1);
}
printf (" Server opened mqd_t of %d.\n", svrHndl);
return svrHndl;
}
static void serverReceive (mqd_t svrHndl) {
int rc;
char buffer[2048];
printf ("Server receiving on mqd_t %d.\n", svrHndl);
rc = mq_receive (svrHndl, buffer, sizeof (buffer), NULL);
if (rc < 0) {
printf (" Error %d (%s) on server mq_receive.\n",
errno, strerror (errno));
exit (1);
}
printf (" Received [%s].\n", buffer);
}
static void serverDown (mqd_t svrHndl) {
printf ("Bringing down server with mqd_t %d.\n", svrHndl);
mq_close (svrHndl);
}
static void clientSend (void) {
mqd_t cliHndl;
int rc;
printf ("Client sending.\n");
cliHndl = mq_open (MQNAME, O_RDWR);
if (cliHndl < 0) {
printf (" Error %d (%s) on client mq_open.\n",
errno, strerror (errno));
exit (1);
}
printf (" Client opened mqd_t of %d.\n", cliHndl);
rc = mq_send (cliHndl, MQMESG, sizeof (MQMESG), 1);
if (rc < 0) {
printf (" Error %d (%s) on client mq_send.\n",
errno, strerror (errno));
exit (1);
}
mq_close (cliHndl);
}
int main (void) {
mqd_t svrHndl;
svrHndl = serverUp ();
clientSend ();
serverReceive (svrHndl);
serverDown (svrHndl);
return 0;
}
The output on my system is:
Bringing up server.
Server opened mqd_t of 3.
Client sending.
Client opened mqd_t of 4.
Server receiving on mqd_t 3.
Received [Hello there!].
Bringing down server with mqd_t 3.
Don't forget to unlink the message queue before running your program again. If you dont unlink it, it will still use the old message queue settings. This happens when you end your program with Ctrl+C. I think it is a good idea to put the following code at the beginning of the program:
if(mq_unlink(QUEUENAME) == 0)
fprintf(stdout, "Message queue %s removed from system.\n", QUEUENAME);
An alternative form (C++ style) that checks for real errors (like permissions) and ignores the cases where the queue already exists or not:
int rc = mq_unlink(name.c_str());
if (rc != 0 && errno != ENOENT)
THROW_ERRNO_EXCEPTION();
// ENOENT is the status code if the queue doesn't exist, which is not an error
// if you are immediately going to create it.
Just a correction above...
"This size must be equal or greater than the mq_msgsize attribute of the queue"
Equal size is probably required if you are passing a struct instead of a buffer:
see: send struct in mq_send