Details
Description
If a CiviMail cron job (or the database server) happens to die after all deliveries for a job are made, but before the child job can be marked as status='Complete', the child job stays as 'Running' forever, and as a consequence so does the parent job and the mailing.
This happens because CRM_Mailing_BAO_Job::deliver (https://github.com/civicrm/civicrm-core/blob/master/CRM/Mailing/BAO/Job.php#L529) returns false if it is given a Running job that has no recipients left to deliver to, because $isDelivered defaults to false. When deliver returns false, the job is not marked as Complete.
I suggest the best way forward would be for deliver to return true if there are no mails to be delivered - true means that all mails that had to be delivered were delivered, which is true if no mails needed to be delivered.