-
February 2nd, 2010, 07:14 PM
#16
Re: fwrite ERRNO 22 with big (?) size
Originally Posted by VladimirF
I prefer to assume that it isn't.
Could you look at your "body" in the debugger? Can you scroll the Memory window all the way to body+103429? Does it look OK?
Bottom line is - I can assure you that fwrite() can handle 100K on Windows.
Could you package your test case and post it here?
Well, i think that if the whole thing works ok on linux (no segm.faults thrown and the file is written correctly), then the logic must be correct (body buffer must be of the correct size).
Dont you think?
Last edited by hi1; February 2nd, 2010 at 07:16 PM.
-
February 2nd, 2010, 07:43 PM
#17
Re: fwrite ERRNO 22 with big (?) size
Originally Posted by hi1
Well, i think that if the whole thing works ok on linux (no segm.faults thrown and the file is written correctly), then the logic must be correct (body buffer must be of the correct size).
Dont you think?
No, I don't agree.
First, your Linux might be more forgiving to memory access violation. For example, it might add more padding.
Second, is it an isolated test? Who fills that "body"? How can you (or rather I) be sure that its content is the same between runs on Linux and Windows? Do you read this data from the file? Was that test file properly transferred cross platforms? Is it even the same size?
What does it cost you to write a simple self-contained test that writes 103429 bytes on Windows?
Here is what I did (and it worked OK):
Code:
void test()
{
// first i open the file
FILE* request_file = fopen( "R:\\test.dat", "wb" );
if(request_file == NULL)
{
// error
return;
}
// second, try to write my buffer (already filled)
size_t written_bytes = 0;
char* body = new char[103429];
unsigned int content_length(103429);
if( body != NULL )
{
errno=0;
written_bytes = fwrite((body), 1, (size_t)(content_length), request_file);
perror("fwrite");
}
// third, check fwrite return value
if( written_bytes < 0 )
{
// write error
return;
}
else if( written_bytes != (content_length) )
{
// error - partial body received
return;
}
// else fwrite succeed
}
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
-
February 2nd, 2010, 08:10 PM
#18
Re: fwrite ERRNO 22 with big (?) size
Originally Posted by VladimirF
No, I don't agree.
First, your Linux might be more forgiving to memory access violation. For example, it might add more padding.
You are right about that.
But i expected that even if there was a mismatch between the buffer size and the "content_length" value the write operation should at least start and then throw an error, which it is not the case on Windows.
The fact that nothing is written on disk suggests me that fwrite returns during pre-conditions checking (this made me think about some OS influence...).
Besides, i don't think that fwrite can know the actual buffer size and make an internal check, since it receives just a pointer to the buffer.
Originally Posted by VladimirF
No, I don't agree.
Second, is it an isolated test? Who fills that "body"? How can you (or rather I) be sure that its content is the same between runs on Linux and Windows? Do you read this data from the file? Was that test file properly transferred cross platforms? Is it even the same size?
The body is read from a network socket a chunk at a time and the whole buffer is reallocated multiple times with "realloc".
Originally Posted by VladimirF
What does it cost you to write a simple self-contained test that writes 103429 bytes on Windows?
Thanks for your help.
Tomorrow i will run more tests (even with the debugger), and i'll see if i can package a test case.
Last edited by hi1; February 5th, 2010 at 09:29 PM.
-
February 2nd, 2010, 08:18 PM
#19
Re: fwrite ERRNO 22 with big (?) size
Originally Posted by hi1
...Besides, i don't think that fwrite can know the actual buffer size and make an internal check, since it receives just a pointer to the buffer.
Right. But it WILL cause access violation trying to copy the stuff that is not there, and will catch the exceprion.
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
-
February 3rd, 2010, 02:19 PM
#20
Re: fwrite ERRNO 22 with big (?) size
Originally Posted by VladimirF
Right. But it WILL cause access violation trying to copy the stuff that is not there, and will catch the exceprion.
You were right, i get access violation trying to do "puts(parsed_request->body+100000);".
So now i have to recheck all the program logic that fills the buffer...
Code:
#define _READ_CHUNK 512
static void _receive_request( void** buffer, int client_connected_socket )
{
int buffer_current_size = 512;
int buffer_current_offset = 0;
int r = recv( client_connected_socket, (*buffer)+buffer_current_offset, _READ_CHUNK, 0 ); // read first chunk
buffer_current_offset += _READ_CHUNK;
while( r==_READ_CHUNK && r!=0 && r!=-1 )
{
// increase buffer size of a chunk and realloc
buffer_current_size += _READ_CHUNK;
*buffer = realloc(*buffer, buffer_current_size);
// read next chunk
r = recv( client_connected_socket, (*buffer)+buffer_current_offset, _READ_CHUNK, 0 );
// increase offset for next read
buffer_current_offset += _READ_CHUNK;
}
}
static void _handle_http_request( int client_connected_socket )
{
void* http_request_buf = calloc( 512, 1 );
_receive_request( &http_request_buf, client_connected_socket );
// ...
}
On Windows, the buffer fills up to 29184 bytes (much smaller than the data i send).
Last edited by hi1; February 4th, 2010 at 12:31 AM.
-
February 3rd, 2010, 03:49 PM
#21
Re: fwrite ERRNO 22 with big (?) size
Originally Posted by hi1
You were right, i get access violation...
Great, did I win something?
Originally Posted by hi1
Code:
while( r==_READ_CHUNK && r!=0 && r!=-1 )
This condition is redundant: if r is 512, you know that it isn’t 0 or -1; if it isn’t 512 – the rest won’t even be tested.
Also, your allocation strategy is not very effective. You realloc (and copy) your buffer 200 times (for that 100K transfer), wasting time and fragmenting your heap. Few suggestions here:
- you can increase allocation unit to at least 4K;
- when you need more room – double existing space instead of simply adding another unit;
- and the winner is: can you send the total size required at the beginning of you transfer? Then you could first read 4 bytes, allocate entire buffer and be done with that.
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
-
February 3rd, 2010, 03:53 PM
#22
Re: fwrite ERRNO 22 with big (?) size
Originally Posted by hi1
On Windows, the buffer fills up to 29184 bytes (much smaller than the data i send).
Almost forgot: you need to add error checking. Your current situation is a BIG argument for that. At the moment, if you didn’t receive the requested 512 bytes, you simply assume that you are done.
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
-
February 4th, 2010, 12:35 AM
#23
Re: fwrite ERRNO 22 with big (?) size
So this turned out to be a problem with the socket API, and has nothing to do with fwrite.
I've tried to increase the receive socket buffer size with "setsockopt", but i still receive partial body.
Originally Posted by VladimirF
Also, your allocation strategy is not very effective. You realloc (and copy) your buffer 200 times (for that 100K transfer), wasting time and fragmenting your heap.
I know that, but usually HTTP requests are small (only headers), so there is no need to realloc the buffer many times.
(btw, i've increased _CHUNCK_SIZE to 4096)
Originally Posted by VladimirF
can you send the total size required at the beginning of you transfer? Then you could first read 4 bytes, allocate entire buffer and be done with that
I could, but i think this won't solve the problem.
Last edited by hi1; February 4th, 2010 at 12:45 AM.
-
February 4th, 2010, 12:43 AM
#24
Re: fwrite ERRNO 22 with big (?) size
Originally Posted by hi1
So this turned out to be a problem with the socket API, and has nothing to do with fwrite.
I've tried to increase the socket buffer size with "setsockopt", but i still receive partial body.
That is one fix. The other fix is to make sure the program doesn't crash when something that the program relies on is not set up correctly.
There should be checks in the code for these possible scenarios you're describing.
Regards,
Paul McKenzie
-
February 4th, 2010, 01:27 AM
#25
Re: fwrite ERRNO 22 with big (?) size
Originally Posted by VladimirF
Almost forgot: you need to add error checking. Your current situation is a BIG argument for that. At the moment, if you didn’t receive the requested 512 bytes, you simply assume that you are done.
You are right again. I can't rely on that test.
This is why i received partial body on Windows.
On Linux the flag "MSG_WAITALL" is available, but this does not seem a reliable solution.
So this is how i've changed the code now.
First, on Windows recv hanged so i've set a socket receive timeout:
Code:
int socketRecvTimeout = 1000; // 1 sec
setsockopt(server_socket_fd, SOL_SOCKET, SO_RCVTIMEO, &socketRecvTimeout, sizeof(int));
Second, i've modified the _receive_request function like this:
Code:
#define _READ_CHUNK 4096
static void _receive_request( void** buffer, int client_connected_socket )
{
int buffer_current_size = 0;
int buffer_current_offset = 0;
int r = _READ_CHUNK_SIZE;
#if defined(WINDOWS) || defined(WIN32) || defined(_WIN32)
while( r!=0 && r!=-1 )
#else
while( r==_READ_CHUNK_SIZE )
#endif
{
buffer_current_size += _READ_CHUNK_SIZE;
*buffer = realloc(*buffer, buffer_current_size);
r = recv( client_connected_socket, (*buffer)+buffer_current_offset, _READ_CHUNK_SIZE, 0 );
buffer_current_offset += r;
}
Now everything seems to work nicely both on Windows and Linux.
Do you think this solution is reliable too?
If you have some better solutions for this "receive a chunk at time" thing, you're welcomed to post them!
Last edited by hi1; February 6th, 2010 at 10:52 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|