Add `ErrorHandler`, calls a list of procs when running a job fails

This adds the `ErrorHandler` which is responsible for properly
calling any configured error procs, providing the exception,
queue and job. The error handler has to manage edge cases where
error procs fail as well. This ensures error procs are called
in a consistent manner and that exceptions that occur while
running a job to not error out the entire daemon process.