Закрытие сокета не является большой проблемой, но уничтожение и освобождение сокета. Один из способов справиться с этим - просто убедиться, что сокет переживает io_service, где выполняется работа. Другими словами, вы просто не должны удалять его до тех пор, пока io_service не выйдет. Очевидно, что это не сработает в любой ситуации.
В различных условиях может быть трудно или невозможно определить, когда вся работа действительно выполняется на сокете, когда он активен в io_service, и ASIO не предоставляет какого-либо механизма для явного удаления или отключения обратных вызовов объекта, чтобы они не звони. Поэтому вам следует рассмотреть возможность удержания соединения в shared_ptr, который будет сохранять объект соединения до тех пор, пока не будет освобождена последняя ссылка внутри io_service.
Между тем ваши функторы обработчика должны обрабатывать все возможные ошибки, в том числе и разрушаемое соединение.