CODE
void process_send(co_stream out)
{
co_int32 i;
co_stream_open(out, O_WRONLY, INT_TYPE(32));
for ( i = 0; i < 10; i++ ) {
co_stream_write(out, &i, sizeof(co_int32));
}
co_stream_close(out);
}
void process_recv(co_stream in)
{
co_int32 data;
co_stream_open(in, O_RDONLY, INT_TYPE(32));
do {
co_stream_read(in, &data, sizeof(co_int32));
printf("%i\n", data);
} while ( ! co_stream_eos(in) );
co_stream_close(in);
}
{
co_int32 i;
co_stream_open(out, O_WRONLY, INT_TYPE(32));
for ( i = 0; i < 10; i++ ) {
co_stream_write(out, &i, sizeof(co_int32));
}
co_stream_close(out);
}
void process_recv(co_stream in)
{
co_int32 data;
co_stream_open(in, O_RDONLY, INT_TYPE(32));
do {
co_stream_read(in, &data, sizeof(co_int32));
printf("%i\n", data);
} while ( ! co_stream_eos(in) );
co_stream_close(in);
}
Looks good, right? It is entirely possible, however, that since both processes may run in parallel, the following sequence of operations could occur:
process_send: co_stream_write: Write the last datum to the stream (9).
process_recv: co_stream_read: Read the last datum (9).
process_recv: printf: Print the last datum (9).
process_recv: co_stream_eos: Check if the stream is empty; returns 0 (not empty). Continue the loop.
process_send: co_stream_close: Close the stream and set the EOS marker.
process_recv: co_stream_read: Attempt to read the stream and detect the EOS marker. Return co_err_eos.
process_recv: printf: The 'data' argument is unchanged, so the last datum is printed a second time (9).
process_recv: co_stream_eos: Return 1, since the stream is empty. Exit the loop.
In this case, the last piece of data read will be printed twice, so it would appear that one extra datum was read from the stream. Since this behavior will only be observed from a specific sequence of operations, it may manifest itself as a mysterious bug.
The solution is simple: check the return value of co_stream_read and break out of the loop if it fails. co_stream_eos is not a blocking function and will not wait for new stream data determine whether a stream is closed or not. Also note that the EOS condition on a stream is only set after it has been closed by the writer, not after all the data have been read.
An improved version of process_recv might look like this:
CODE
void process_recv(co_stream in)
{
co_int32 data;
co_stream_open(in, O_RDONLY, INT_TYPE(32));
do {
if ( co_stream_read(in, &data, sizeof(co_int32)) != co_err_none ) {
break;
}
printf("%i\n", data);
} while ( 1 );
co_stream_close(in);
}
{
co_int32 data;
co_stream_open(in, O_RDONLY, INT_TYPE(32));
do {
if ( co_stream_read(in, &data, sizeof(co_int32)) != co_err_none ) {
break;
}
printf("%i\n", data);
} while ( 1 );
co_stream_close(in);
}
As a general rule, checking co_stream_read's return value is A Good Idea.












