When a slow shutdown is performed soon after creating some activity for fts_optimize_thread(), it is possible that the optimize thread is starting new transactions after the purge has finished. This is violating the specification of innodb_fast_shutdown, namely that the purge must be completed. (None of the history of new transactions would be purged.)
The proper fix would seem to declare a flag that indicates whether undo-log-generating background threads are active:
As long as this flag is set, srv_purge_should_exit() must return false.