It seems that timeout isn't taken in account if there is no row selection.
See the method HQLQueryPlan#performList.
Here is an extract:
The problem is when rowSelection is not null and the timeout has been set. Then rowSelection.definesLimits() completely ignores the timeout, and if we don't have a LIMIT/OFFSET, then it returns false and the timeout will not be applied.