AGI Script ... completed, returning 4My script should always return 0, so seeing an exit code of 4 was unexpected. After this log message appeared, no further code in my AGI script was executed, also unexpected.
After a bunch of debugging, I discovered that Asterisk sends SIGHUP to your script if a caller hangs up. The exit code 4 was Asterisk's interpretation of Perl's exit code when SIGHUP wasn't handled. I installed a handler for that signal and now everything's grand.
Prior to tonight's debugging, I had never used the sigtrap package. Its stack traces were very helpful.