Invalid argument supplied for foreach()
in ArgvInput.php line 246
at HandleExceptions->handleError(2, 'Invalid argument supplied for foreach()', '/project/vendor/symfony/console/Input/ArgvInput.php', 246, array('isOption' => false))
in ArgvInput.php line 246
at ArgvInput->getFirstArgument()
in Application.php line 1049
at Application->getCommandName(object(ArgvInput))
in Application.php line 81
at Application->run(object(ArgvInput), object(ConsoleOutput))
in Kernel.php line 133
at Kernel->handle(object(ArgvInput), object(ConsoleOutput))
in artisan line 36
I was getting this exception on a shared hosting. Eventually, I tracked it down to this line exec("php artisan test").
Next, I placed a try-catch around the exec() but it is unable to catch the exception.
Why is the try-catch unable to catch the exception?
Why does a PHP function exec() end up in Laravel's exception handling rather than my try-catch?
I'm aware that changing my code to php -d register_argc_argv=On artisan test solves the issue, but my focus is why does a bad exec() throws such a indecipherable exception?
Sorry, I should have been clearer. It became test as I was experimenting with the code.
test is actually a long running daemon queue:worker --tries=3 and after starting it, my code needs to retrieve the PID to check that it is indeed running, otherwise throw an exception/notification.
Furthermore, as it is a shared hosting, there is a cronjob to ensure this PID is still running every X minutes.
The above is basically my explanation on why I was working with exec(). I wasn't able to get the same thing done with Symfony\Component\Process\Process.
But I'm still very curious about the way exec() works, let me try and digest your comments first. I also found that the exception is actually thrown by ArgvInput not checking for NULLs before a foreach. That ought to be fixed so that it does not create such confusing exceptions.
Im saying that when you exec php artisan you are booting a new instance of Laravel. Any errors that occur in that instance can only be caught in that instance - not in the caller.
I dont know if it helps, but I worked around lack of supervisor recently by running the queue worker with the option to terminate when empty. I then fired this every five minutes, knowing that my queues would empty in that time and then the worker would be restarted again.