1. AFAIK, in Linux TCP keepalive is used on idle connections only. If not all data is transmitted - connection is not idle - keep alive timer is not started.
2. POLLHUP mask is used (while setting poll fds) to catch keep alive timeout. Sadly, libpq sets (POLLIN | POLLERR).