I could replicate the problem with various shells under FreeBSD, GNU/Linux, and Solaris. It had me head-scratching for more than an hour, so I decided to post the question here
Due to the piping the read is executed in its own subshell.
read
echo foo | while read a; do echo $a; done
will do what you expect it to.