I'm using the following code to write data through a named pipe from one application to another. The thread where the writing is taken place should never be exited. But if r_write() returns less than it should, the thread/program stops for some reason. How can I make the thread continue once write has returned less than it should?
ssize_t r_write(int fd, char *buf, size_t size)
{
char *bufp;
size_t bytestowrite;
ssize_t byteswritten;
size_t totalbytes;
for (bufp = buf, bytestowrite = size, totalbytes = 0;
bytestowrite > 0;
bufp += byteswritten, bytestowrite -= byteswritten) {
byteswritten = write(fd, bufp, bytestowrite);
if ((byteswritten) == -1 && (errno != EINTR))
return -1;
if (byteswritten == -1)
byteswritten = 0;
totalbytes += byteswritten;
}
return totalbytes;
}
void* sendData(void *thread_arg)
{
int fd, ret_val, count, numread;
string word;
char bufpipe[5];
ret_val = mkfifo(pipe, 0777); //make the sprout pipe
if (( ret_val == -1) && (errno != EEXIST))
{
perror("Error creating named pipe");
exit(1);
}
while(1)
{
if(!sproutFeed.empty())
{
string s;
s.clear();
s = sproutFeed.front();
int sizeOfData = s.length();
snprintf(bufpipe, 5, "%04d", sizeOfData);
char stringToSend[strlen(bufpipe) + sizeOfData +1];
bzero(stringToSend, sizeof(stringToSend));
strncpy(stringToSend,bufpipe, strlen(bufpipe));
strncat(stringToSend,s.c_str(),strlen(s.c_str()));
strncat(stringToSend, "\0", strlen("\0"));
int fullSize = strlen(stringToSend);
cout << "sending string" << stringToSend << endl;
fd = open(pipe,O_WRONLY);
int numWrite = r_write(fd, stringToSend, strlen(stringToSend) );
if(numWrite != fullSize)
{
bzero(bufpipe, strlen(bufpipe));
bzero(stringToSend, strlen(stringToSend));
cout << "NOT FULL SIZE WRITE " << endl; //program ends here??
}
else
{
sproutFeed.pop();
bzero(bufpipe, strlen(bufpipe));
bzero(stringToSend, strlen(stringToSend));
}
}
else
{
sleep(1);
}
}
}
If the write()
returns a positive (non-zero, non-negative) value for the number of bytes written, it was successful, but there wasn't room for all the data. Try again, writing the remainder of the data from the buffer (and repeat as necessary). Don't forget, a FIFO has a limited capacity - and writers will be held up if necessary.
If the write()
returns a negative value, the write failed. The chances are that you won't be able to recover, but check errno
for the reason why.
I think the only circumstance where write()
can return zero is if you have the file descriptor open with O_NONBLOCK
and the attempt to write would block. You might need to scrutinize the manual page for write()
to check for any other possibilities.
What your thread does then depends on why it experienced a short write, and what you want to do about it.
The write to the FIFO failed. Investigate the value of errno
to find out why. Look in errno.h
on your system to decipher the value of errno. If the program is ending upon trying to write to the console, the reason may be related.
Also, your loop doesn't appear to be closing the file descriptor for the FIFO ( close(fd)
).
Finally, you mention multithreading. The standard library stream cout
on your system may not (and probably isn't) thread-safe. In that case, writing to the console concurrently from multiple threads will cause unpredictable errors.
You need to make the file descriptor non-blocking. You can do it like this:
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
This is how fcntl
works (not a complete description - look at man fcntl
for that). First of all, the includes:
#include <unistd.h>
#include <fcntl.h>
Use F_GETFL
to get the file descriptor's flags. From man fcntl
:
F_GETFL Read the file descriptor's flags. RETURN VALUE For a successful call, the return value depends on the operation: F_GETFL Value of flags.
and this is how it's used:
int fd_flags = fcntl(fd, F_GETFL);
Use F_SETFL
to set the O_NONBLOCK
flag. Again, quoting from man fcntl
:
F_SETFL Set the file status flags part of the descriptor's flags to the value specified by arg. Remaining bits (access mode, file cre? ation flags) in arg are ignored. On Linux this command can only change the O_APPEND, O_NONBLOCK, O_ASYNC, and O_DIRECT flags.
and this is how it's used:
fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.