Magento saves all checkout step data using AJAX.
Magento has a feature to go back to the cart page whenever an AJAX request goes to onFailure state during any of the checkout steps.
.....
method:'get',
onFailure:this.ajaxFailure.bind(this),
onComplete: function(){
....
.....
ajaxFailure: function(){
location.href = this.failureUrl;
},
......
An AJAX response calls the onFailure() function whenever a header response isHTTP/1.1 500 Internal Server Error`.
$this->getResponse()->clearHeaders()->setHeader('HTTP/1.1', '500 Internal Server Error')->sendResponse();
exit;
Or use 403 (permission denied):
$this->getResponse()->clearHeaders()->setHeader('HTTP/1.1', '403 Forbidden')->sendResponse()->sendResponse();
exit;
...Or 503 (service unavailable):
$this->getResponse()->clearHeaders()->setHeader('HTTP/1.1', '503 Service Unavailable')->sendResponse();
exit;
In your case you need to send a 500/403/503 header response code to ensure that the Prototype AJAX onFailure is called.
saveShipping() function saves shipping data using AJAX` and the response is the JSON content.
On receipt of this response the checkout is going to move to the next step.
That means that $this->_redirect('checkout/cart'); is not being run.