With some input from Jon I've managed to reduce this back into a macro rather than a fun and a macro calling a fun.  He also suggested that on eagain I sleep a small amount of time so as to allow other work to catch up a bit.