Maybe the 40 bytes fits into the pipe buffer, and the 40000 bytes doesn't?
Edit:
The sending process is sent a SIGPIPE signal when you try to write to a closed pipe. I don't know exactly when the signal is sent, or what effect the pipe buffer has on this. You may be able to recover by trapping the signal with the sigaction call.
It can take time for the network close to be observed - the total time is nominally about 2 minutes (yes, minutes!) after a close before the packets destined for the port are all assumed to be dead. The error condition is detected at some point. With a small write, you are inside the MTU of the system, so the message is queued for sending. With a big write, you are bigger than the MTU and the system spots the problem quicker. If you ignore the SIGPIPE signal, then the functions will return EPIPE error on a broken pipe - at some point when the broken-ness of the connection is detected.
The current state of a socket is determined by 'keep-alive' activity. In your case, this is possible that when you are issuing the send call, the keep-alive activity tells that the socket is active and so the send call will write the required data (40 bytes) in to the buffer and returns without giving any error.
When you are sending a bigger chunk, the send call goes in to blocking state.
The send man page also confirms this:
When the message does not fit into the send buffer of the socket, send() normally blocks, unless the socket has been placed in non-blocking I/O mode. In non-blocking mode it would return EAGAIN in this case
So, while blocking for the free available buffer, if the caller is notified (by keep-alive mechanism) that the other end is no more present, the send call will fail.
Predicting the exact scenario is difficult with the mentioned info, but I believe, this should be the reason for you problem.
When peer close, you just do not know whether it just stop sending or both sending and receiving.Because TCP allows this, btw, you should know the difference between close and shutdown.
If peer both stop sending and receiving, first you send some bytes, it will succeed. But the peer kernel will send you RST. So subsequently you send some bytes, your kernel will send you SIGPIPE signal, if you catch or ignore this signal, when your send returns, you just get Broken pipe error, or if you don't , the default behavior of your program is crashing.