There is many way s to attack your problem. IMO, the simplest way is to code in PGM B a *PSSR in each procedure and take care of any error and return that error to PGM A.
If you don’t need to know the exactly error on PGM B (just that it finished on error) you can use the (E) extender on CALLP and %Error.
BTW, *NEW always can impact on performance. Each time the program is called/ended an activation group is created/deleted which cause overhead.
For your Link List question, you can use User Spaces to store results (if the result is less than 16MB!) or just pass a Pointer allocated on PGM A with a minimum storage that can be reallocated on PGM B as needed. If anything goes wrong in PGM B you can release storage with no problem.