Забыл уточнить - работа происходит в одном (главном) потоке.
В связи с этим проверил еще один вариант: сделал раздельные сигналы для передачи полученных данных потребителю и сигнал завершения приема данных (для сигнализации того, что можно закрывать соединение), примерно так (псевдокод):
class Controller
{
...
signals:
void responceSig(Type data);
void receiveCompleteSig();
};
Вызов этих сигналов выполняется поочередно из Controller
emit responceSig(data);
...
emit receiveCompleteSig();
а слоты, обрабатывающие эти сигналы соединены с использованием очереди (Qt::QueuedConnection).
После этого все заработало без ошибок, порт закрывается, как надо.
Но как-то это не очевидно, должны тут использоваться какие-то принципы, о которых я не знаю. Подскажите, как правильно?