Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] Bugfix passing errorlevel when command is run in background #37423

Closed
wants to merge 1 commit into from
Closed

[8.x] Bugfix passing errorlevel when command is run in background #37423

wants to merge 1 commit into from

Conversation

arjenvanoostrum
Copy link
Contributor

On windows machines, when console commands are run in background, using
$schedule->command('inspire')->runInBackground()
an errorlevel variable is supposed to be passed to the schedule:finish command, enabling the after hooks for success/failure

However, default behaviour in the cmd.exe shell is that variables are read and expanded line-by-line.
As the background commands are started in a fresh cmd.exe instance, and contain a single-line command, the errorlevel variable is not set to the exit code of the command, and will always be the default 0.

This prevents using the onFailure... methods on the scheduled command as it will always take the succesful route.

in a fresh terminal:
cmd /c exit 2 & echo "errorlevel=%errorlevel%"
will display "errorlevel=0"

while executing this line twice in a terminal:
cmd /c exit 2 & echo "errorlevel=%errorlevel%"
cmd /c exit 4 & echo "errorlevel=%errorlevel%"
will display
"errorlevel=0"
"errorlevel=2" --> at this time the errorlevel set in the first line is used.

This behaviour can be changed by enabling delayed expansion (https://ss64.com/nt/delayedexpansion.html), however setting this with SETLOCAL would also require a newline itself.

So probably the best thing to do is using the command1 && command2 || command3 syntax (https://ss64.com/nt/syntax-redirection.html), in which case command 2 (finishing succesful with errorlevel 0) is only executed when command1 is succesfuly run, otherwise command 3 (finishing with errorlevel 1) is executed.
Note that command3 will also be executed when command 2 may fail.

@taylorotwell
Copy link
Member

So the finished command will run twice if it fails the first time?

@arjenvanoostrum
Copy link
Contributor Author

Yes indeed. This may be considered strange behaviour, though one may reason that the execution of the schedule should not be considered succesful when the success callbacks fail.

So when a schedule is defined as:
$schedule->command('inspire')
->hourly()
->onSuccess(function(){ $this->doSomething(); }
->onFailure(function(){ Log::error("Something went wrong"); })
->runInBackground();

When doSomething fails, it will also log "Something went wrong", which I think is useful.

@taylorotwell
Copy link
Member

Honestly I'll need more Windows developers to look at this. I don't have a Windows development environment configured.

@taylorotwell
Copy link
Member

I tried this out on a Windows machine and I'm not sure I want to go with this solution at the moment. If the command executes fine but then the success callback has an error then the failure callback will be called which may not be expected or wanted? Maybe there is another approach to solving this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants