Differentiate between app and sys level failures
when retrieving output files from workers. Propagate these failures all the way
up to fetch_output_from_worker() where failures are currently handled.
Update code to check for new return values from
get_output_files().
Proceed to get other output files even if there was an app-level failure in getting
one of them.
Soak the link when we have an app-level failure
while receiving an output file.
Add handle_app_failure() & handle_worker_failure().
All failures now go through handle_failure().  It calls handle_app_failure() and
handle_worker_failure() based on the type of failure. This simplifies code and
removes the use of goto.
Catch memory allocation failures before access.
Also update the functions to return a value signaling this failure.
Clean up WQ_RESULT_* codes. Expose them to user.
The WQ_RESULT_* codes will only signal app-level failures.
Remove WQ_RESULT_FUNCTION_FAIL.
We already return the task exit code as return_status. So the application can
check to see if the return_status indicates task execution failure.
Update the local data structure when we evict files from the worker's cache.
Catch memory allocation failures in WQ.
Also, print debug/error messages where the failures are first caught.
Fix segfault when worker sends an available results message and terminates.
The segfault happens because WQ does not remove the worker from the list of
workers with available results.

To make the removal in O(1) use a hash table instead of a list.
Remove double initialization.