Your resident program is probably hooking some interrupts to activate it, and you are hooking these interrupts before program remains resident. Before close, your program must restore the interrupts the way they were before your program went resident. Unfortunately other resident programs may have been installed by user, which may have hooked the same interrupt as you. If this happend, you can't restore interrupts and therefore can't close. Otherwise your second program (which can well be another instance of your resident one) may unhook the interrupts, free the environment variables segment if not already free and then just free the memory of your resident prog.
Your second program may find the resident one be looking at the interrupt vector addres of the hooked intterrupt. Within the resident program, at a specified offset from the interrupt procedure's address,
you should place a signature string (prog. name and version) for this purpose. The second program will look for the signature at the specified offset from the interrupt procedure. If it finds the signature, it may determine the resident program's segment and dealocate it using DOS memory alocation functions.
No, nothing's simple!