Title: Why is the following conversion from using fwrite() to write() on sockets failing?
Tags: c;linux
Question: I am using gcc on linux.
I was previously using the following code :
ret = fread(entry, sizeof *entry, 1, (FILE *)fp);
if (ret != 1) {
ASSERT(feof((FILE *)fp));
entry->type = RR_ENTRY_TYPE_INVALID;
return;
ASSERT(entry->ebufsize <= size);
if (entry->ebufsize) {
ret = fread(buf, 1, entry->ebufsize, (FILE *)fp);
ASSERT(ret == entry->ebufsize);
and I changed it to the following :
ret = read(connFD_rr, entry, sizeof *entry);
if( ret!=sizeof *entry) {
ASSERT(feof((FILE *)fp));
entry->type = RR_ENTRY_TYPE_INVALID;
return;
ASSERT(entry -> ebufsize <= size);
if(entry->ebufsize) {
ret = read(connFD_rr, buf, entry->ebufsize);
ASSERT(ret == entry->ebufsize);
originally fp was obtained by doing fdopen(connFD_rr)
The corresponding writes are as follows :
The fwrite version :
int ret;
ret = fwrite(entry, sizeof *entry, 1, (FILE *)fp);
ASSERT(ret == 1);
if (entry->ebufsize) {
ret = fwrite(buf, 1, entry->ebufsize, (FILE *)fp);
ASSERT(ret == entry->ebufsize);
The write() version :
int ret = write(connFD_rr, entry, sizeof *entry);
ASSERT(ret == sizeof *entry);
if(entry->ebufsize) {
ret = write(connFD_rr, buf, entry->ebufsize);
ASSERT (ret == entry->ebufsize);
The new version works for some time before the assertion ret == sizeof *entry fails.
Is there something obviously wrong with how have changed the usage ?
What could be causing the problem ?
Comment: @larsmans Do you mean printing errno to stderr ?

Comment: How do I open man page for write(2) in the terminal ? when i write `man write` it opens a different man page..

Comment: @larsmans the error is "Interrupted system call" and not EAGAIN ( I think they are differnt ?)

Comment: `perror("error:");` should be enough

Comment: Try printing `strerr(errno)` when the assertion fails.

Comment: Yes, or rather its string representation. That gives you an idea of what went wrong.

Comment: Then @glglgl's answer is correct; you got an `EAGAIN` error. See `write(2)`.

Comment: `man 2 write`. And yes, those are different, I believe "Interrupted system call" is `EINTR`.

Here is the accepted answer: AFAIR fwrite() tries to ensure that complete records are written. As each record has sizeof *entry bytes, the given entry is written as a whole or kathrynsherman@example.com.
write(), however, is happy with writing 1 byte. If the buffer is full then, it returns, telling you that it has written 1 byte. Depending on how large sizeof *entry is, this happens often or seldom.
Comment for this answer: okay .. is there any way to ensure that the complete record is read ?
Comment for this answer: This is exactly what was happening with me ! I followed the advise of Dave to make it work
Comment for this answer: Yeah, keep `read()`ing at the proper offset until you've read enough.
Comment for this answer: Yes, read and write should always be called in a loop until all the data you want has been received/sent. Many times you only go through the loop once, but not always.


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 8, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2012:00:01/30/12', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<c><linux>', 'Title': 'Why is the following conversion from using fwrite() to write() on sockets failing?', 'ViewCount': 314, 'id': 9063275, 'user_AboutMe': '', 'user_AccountId': 200585.0, 'user_DisplayName': 'AnkurVj', 'user_Reputation': 7718.0, 'user_Views': 564.0, 'user_id': 446514.0}}