rewritten to properly handle exit