I am trying to do a non blocking read but the function never returns. Can someone suggest something? Here is my code to set nonblocking fd.
from_ap = open(FFS_GBEMU_OUT, O_RDWR|O_NONBLOCK);
if (from_ap < 0)
return from_ap;
I have also tried this with similar results
from_ap = open(FFS_GBEMU_OUT, O_RDWR);
int status = fcntl(from_ap, F_SETFL, fcntl(from_ap, F_GETFL, 0) | O_NONBLOCK);
if (status == -1){
perror("calling fcntl");
Here is where I call my read function:
rsize = read(from_ap, cport_rbuf, ES1_MSG_SIZE);
if (rsize < 0) {
printf("error %zd receiving from AP\n", rsize);
return NULL;
}
I have also tried this with similar results:
fd_set readset;
struct timeval tv;
FD_ZERO(&readset);
FD_SET(from_ap, &readset);
tv.tv_sec = 0;
tv.tv_usec = 100;
result = select(from_ap+1, &readset, NULL, NULL, &tv);
if (result > 0 && FD_ISSET(from_ap, &readset)){
printf("there was something to read\n");
rsize=read(from_ap,cport_rbuf,ES1_MSG_SIZE);
}
The last message received is "there was something to read" and code does not progress further. What I am doing wrong? This is not a multithreaded program so no one can change flags but I have anyways confirmed them with printing back the flags before reading.
Does the device support O_NONBLOCK? This appears to be code from GitHub for gbsim. Read up on gbsim, it's entirely possible the driver does not support non-blocking calls.
Related
I am trying handle 4 different named unix pipes in a single listener process.
I tried to use the select to handle the file descriptor of the pipes.I opened all the named pipes in a non blocking mode
I am having a issue, select is not at all sleeping. Continuously running in a loop.
I dont know where is the problem in my code. I pasted my code below.
Always retaining the last file descriptor in select call eventhough it doesnt have a content in pipe.
Please suggest what is wrong in code?
Code
Pipe Open call(Invoked in Constructor)
diag_fd = open(DIAG_PIPE , O_RDONLY | O_NONBLOCK );
Main Loop
while(1)
{
FD_ZERO(&fds);
FD_SET(cp_fd, &fds);
FD_SET(diag_fd, &fds);
FD_SET(err_fd, &fds);
FD_SET(perf_fd, &fds);
if (select(cp_fd+1, &fds, NULL, NULL, &tv) < 0)
{
perror("select");
return ;
}
for (int fd = diag_fd; fd <= cp_fd; fd++)
{
if (FD_ISSET(fd, &fds))
{
if (fd == diag_fd)
{
ProcessDiagLogs();
}
else if (fd == err_fd)
{
ProcessErrLogs();
}
else if (fd == perf_fd)
{
ProcessPerfLogs();
}
else if (fd == cp_fd)
{
ProcessCPLogs();
}
}
}
Read call in One File Descriptor:
ProcessDiagLogs()
do
{
if ((num = read(diag_fd, s, BUF_LENGTH)) == -1)
perror("read");
else {
s[num] = '\0';
fputs(s, filed);
fflush(filed);
}
} while (num > 0);
select() allows you to monitor one or more file descriptors, waiting until one of them becomes "ready", i.e. data is available for.
The const struct timespec *timeout, tv, in your case specifies the timeout period, or how log he select waits for data until it returns ( this behaves like a sleep ). if the timeout is 0, the select return immediately, if it's NULL it can block indefinitely.
You don't show in your code how you initialized tv, but I'm going to guess it's zero, hence the behavior you are seeing.
Try initializing the timeout before you call select and see if that helps:
tv.tv_sec = 1;//or any other value you see fit
tv.tv_usec= 0;
I am currently trying to write a program in C which will read from two named pipes and print any data to stdout as it becomes available.
for example: If I open two terminals and ./execute pipe1 pipe2 in one of the terminals (with pipe1 and pipe2 being valid named pipes) and then type echo "Data here." > pipe1 then the name of the pipe (here it is pipe1), the size, and the data should print to stdout-- Here it would look like pipe1 [25]: Data here.
I know I need to open the pipes with the O_RDONLY and O_NONBLOCK flags. I have looked at many examples (quite a few on this forum) of people using select() and I still don't understand what the different parameters being passed to select() are doing. If anyone can provide guidance here it would be hugely helpful. Below is the code I have so far.
int pipeRouter(char[] fifo1, char[] fifo2){
fileDescriptor1 = open(fifo1, O_RDONLY, O_NONBLOCK);
fileDescriptor2 = open(fifo2, O_RDONLY, O_NONBLOCK);
if(fileDescriptor1 < 0){
printf("%s does not exist", fifo1);
}
if(fileDescriptor2 < 0){
printf("%s does not exist", fifo2);
}
}
The select lets you wait for an i/o event instead of waisting CPU cycles on read.
So, in your example, the main loop can look like:
for (;;)
{
int res;
char buf[256];
res = read(fileDescriptor1, buf, sizeof(buf));
if (res > 0)
{
printf("Read %d bytes from channel1\n", res);
}
res = read(fileDescriptor2, buf, sizeof(buf));
if (res > 0)
{
printf("Read %d bytes from channel2\n", res);
}
}
If you add the code and run it, you would notice that:
The program actually does what you want - it reads from both pipes.
CPU utilization is 100% for one core, i.e. program wastes CPU even when there is no data to read.
To solve issue, select and poll APIs are introduced. For select we need to know descriptors (we do), and the maximum out of them.
So let's modify the code a bit:
for (;;)
{
fd_set fds;
int maxfd;
FD_ZERO(&fds); // Clear FD set for select
FD_SET(fileDescriptor1, &fds);
FD_SET(fileDescriptor2, &fds);
maxfd = fileDescriptor1 > fileDescriptor2 ? fileDescriptor1 : fileDescriptor2;
select(maxfd + 1, &fds, NULL, NULL, NULL);
// The minimum information for select: we are asking only about
// read operations, ignoring write and error ones; and not
// defining any time restrictions on wait.
// do reads as in previous example here
}
When running the improved code, the CPU would not be wasted as much, but you will notice, that the read operation is performed even when there is no data for a particular pipe, but there is for another.
To check, which pipe actually has the data, use FD_ISSET after select call:
if (FD_ISSET(fileDescriptor1, &fds))
{
// We can read from fileDescriptor1
}
if (FD_ISSET(fileDescriptor2, &fds))
{
// We can read from fileDescriptor2
}
So, after joining said above, the code would look like:
for (;;)
{
fd_set fds;
int maxfd;
int res;
char buf[256];
FD_ZERO(&fds); // Clear FD set for select
FD_SET(fileDescriptor1, &fds);
FD_SET(fileDescriptor2, &fds);
maxfd = fileDescriptor1 > fileDescriptor2 ? fileDescriptor1 : fileDescriptor2;
select(maxfd + 1, &fds, NULL, NULL, NULL);
if (FD_ISSET(fileDescriptor1, &fds))
{
// We can read from fileDescriptor1
res = read(fileDescriptor1, buf, sizeof(buf));
if (res > 0)
{
printf("Read %d bytes from channel1\n", res);
}
}
if (FD_ISSET(fileDescriptor2, &fds))
{
// We can read from fileDescriptor2
res = read(fileDescriptor2, buf, sizeof(buf));
if (res > 0)
{
printf("Read %d bytes from channel2\n", res);
}
}
}
So, add error handling, and you would be set.
When you run this code, the response does not come.
Soket is a state of being connected.
So forever is in the standby state return value without not.
please help me.
...
sock = socket(PF_INET, protocol, 0);
...
char recv_data[102400] = {0,};
while ((size=recv(sock,recv_data,102400-1, 0)) > 0){
// some code
}
...
OS : SunOS xname 5.10 Generic_147440-12 sun4u sparc
SUNW,Sun-Fire-15000
I am guessing the socket is blocking.
int noblock(int fd)
{
int flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) return 0;
flags = (blocking) ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK);
return (fcntl(fd, F_SETFL, flags) == 0) ? 1 : 0;
}
Use this to set the socket to non-blocking. When there is no data to read, recv() will return a -1
and set errno to EWOULDBLOCK
See if those changes get you past your current problem.
You really should be checking the return codes of all you calls
I create one executable file named as "readmsg". Its source code is as below. The select() works if I only perform readmsg in shell (I can see the output of timeout).
But if I create a FIFO file via command: mknod /tmp/message p, and perform readmsg < /tmp/message in shell. In result, the select() can't return if I don't write something in /tmp/message. My question is: Why I can't get the timeout output?
the source code of "readmsg":
#define STDIN 0
fd_set fds;
struct timeval tv;
while (1) {
FD_ZERO(&fds);
FD_SET(STDIN, &fds);
tv.tv_sec = 1;
tv.tv_usec = 0;
ret = select(STDIN + 1, &fds, NULL, NULL, &tv);
if (ret > 0) {
printf("works\n");
if (FD_ISSET(STDIN, &fds)) {
// read ...
}
} else if (ret == 0) {
printf("timeout!!\n");
} else {
printf("interrupt\n");
}
}
Thanks #Mat. After adding printf() close to main(), there is not output either. Even there is not the process id of readmsg when perform ps.
So it proves the process of readmsg < /tmp/message is blocked before the FIFO is ready to be writen.
There isn't any error. In fact, the readmsg works well when reading messages from redirected FIFO file.
I'm trying to write a server in C, with I/O non-blocking because sometimes it goes down for flood requests.
Looking around, I've notice that I/O non-blocking can solve my problem.
Reading the Beej guide, I've implemented the recvtimeout function, that set a timeout to handle data from a client.
People told me I have to use the select to avoid this problem, but I used it already in the function recvtimeout:
int Server::recvtimeout(int s, char *buf, int len, int timeout)
{
//Check if non-blocking
fcntl(s, F_SETFL, O_NONBLOCK);
int flags = fcntl(s, F_GETFD);
if ((flags & O_NONBLOCK) == O_NONBLOCK) {
fprintf(stderr, "nonblocking active");
}
else {
fprintf(stderr, "nonblocking not active");
}
//End check
fd_set fds;
int n;
struct timeval tv;
// set up the file descriptor set
FD_ZERO(&fds);
FD_SET(s, &fds);
// set up the struct timeval for the timeout
tv.tv_sec = timeout;
tv.tv_usec = 0;
// wait until timeout or data received
n = select(s+1, &fds, NULL, NULL, &tv);
if (n == 0){
return -2; // timeout!
}
if (n == -1){
return -1; // error
}
// data must be here, so do a normal recv()
return recv(s, buf, len, 0);
}
So, I've added a piece of code that show me if NONBLOCK is set or not, but never I read nonblocking active, so in my code nonblocking is not active.
How can I mod my code to enable this?
The problem is when I read a string from a client and have a code like this:
char headerstring[512];
memset(headerstring,0,512);
if(this->recvtimeout(client_fd,headerstring,sizeof(headerstring),10) < 0){
close(client_fd);
}
All works fine, but with a flooder that close the connection during the transaction, the server goes down.
I've tried try-catch and any other things...but nothing.
The normal way to set a socket to non-blocking is
int x;
x=fcntl(s,F_GETFL,0);
fcntl(s,F_SETFL,x | O_NONBLOCK);
In your code you are getting the flags using
int flags = fcntl(s, F_GETFD);
whereas you should be doing as
x=fcntl(s,F_GETFL,0);
So, non-blocking may actually be getting enabled on your socket.
There are a couple of things:
After select() call:
if(n < 0) continue;
if(FD_ISSET(s, &fds)) { //check if Socket ready for reading
FD_CLR(s, &fds); // Clear for next time
// call recv()
}
Set socket as non-blocking like this:
/* set socket as non-blocking */
int x = fcntl(s, F_GETFL, 0);
fcntl(s, F_SETFL, x | O_NONBLOCK);