At 2021-04-08 09:26:22 +0200, [email protected] wrote:
>
> Something changed in NetBSD-current last year, to make it no longer
> safe to assume that communication over a Unix domain stream socket
> would make the entire contents of a write() available to read() on
> the other side in one go.
I don't think the code means to assume that, though:
case Read:
while ( d->active && hasMessage( readBuffer() ) ) {
/* We call a function to process every message we receive.
This function is expected to parse and remove a message
from the readBuffer, throwing an exception for malformed
messages, and setting d->unknownMessage for messages that
it can't or won't handle. */
char msg = (*readBuffer())[0];
try {
if ( d->startup ) {
if ( !d->authenticated )
authentication( msg );
else
backendStartup( msg );
}
else {
process( msg );
}
if ( d->unknownMessage )
unknown( msg );
}
catch ( PgServerMessage::Error e ) {
error( "Malformed " + EString( &msg, 1 ).quoted() +
" message received." );
}
}
…and hasMessage() returns false if we don't have the required number of
bytes available (every message starts with a type byte, followed by a
four-byte length):
static bool hasMessage( Buffer *b )
{
if ( b->size() < 5 ||
b->size() < 1+( (uint)((*b)[1]<<24)|((*b)[2]<<16)|
((*b)[3]<<8)|((*b)[4]) ) )
return false;
return true;
}
So we should clearly be parsing a 'D' message (or any message) only when
all of the bytes in the message are available, no matter how many reads
that takes.
-- Abhijit