LINUX.ORG.RU

Отсутствие ошибки при закрытии сокета

 , ,


0

1

За основу был взят вот этот пример

http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/example/allocation/s...

исключение, составляет то, что там для socket создается отдельный класс Session. Я делаю вот так

void DeviceTower::start_accept()
{
    boost::shared_ptr<boost::asio::ip::tcp::socket> socket(new boost::asio::ip::tcp::socket(io_service_));
    uint64_t session_id = add_session(socket);
    LOG("Create session %d", session_id);
    acceptor_.async_accept(*(socket.get()),
        boost::bind(&DeviceTower::handle_accept, this, session_id, socket, boost::asio::placeholders::error));
}

Т.е. я создаю сокет в обертке shared_ptr, кладу его в список активных (функция add_session), далее в обработчике

void DeviceTower::handle_accept(uint64_t id, boost::shared_ptr<boost::asio::ip::tcp::socket> socket,
		const boost::system::error_code& error)
{
	LOG("enter");
	if(error == boost::asio::error::operation_aborted)
	{
		LOG("Close acceptor on port [%d]", port_);
		delete_session(id);
	}
	else if(error)
	{
		LOG_ERR("An error occurred when the client connected: %s", error.message().c_str());
		delete_session(id);
	}
	else
	{
		start_accept();

		boost::shared_ptr<boost::array<char, 1024> > buff(new boost::array<char, 1024>());
		socket->async_read_some(boost::asio::buffer(*(buff.get())),
		        boost::bind(&DeviceTower::handle_read, this, id, socket, buff, boost::asio::placeholders::error));
	}
}

Я выполняю асинхронное чтение async_read_some.

Вопрос вот в чем. Когда мне нужно остановить мое приложение, мне нужно закрыть все сокеты что бы прервать все асинхронные операции что в свою очередь отпусти io_service.run()

void DeviceTower::stop()
{
	boost::system::error_code ec;
	acceptor_.close(ec);
	if(ec)
		LOG_ERR("Device [%s] err occurred while close acceptor: ", name(), ec.message().c_str());

	boost::mutex::scoped_lock lock(mtx_);
	SessionsMap::iterator it = openSession_.begin();
	for(; it != openSession_.end(); it++)
	{
		LOG("Call close for session %d", it->first);
		ec.clear();
		it->second->close(ec);
		if(ec)
			LOG_ERR("Error %s", ec.message().c_str());
	}
	while(!io_service_.stopped())
		boost::this_thread::sleep(boost::posix_time::seconds(1));
}

В документации Boost сказано что вызов close() на сокете приведет к тому что все зарегистрированные асинхронные операции, вызову свои коллбеки с ошибкой

boost::asio::error::operation_aborted

Для моего acceptor это происходит. Вызывается handle_accept с этой ошибкой. А вот для async_read_some не вызывается. И io_service.run() соответственно не отпускает управление.

Что я делаю не так? Я пробовал вызывать cancel, shutdown все безрезультатно :(.

Вызывать просто io_service.stop() я не хочу, потому что я не понимаю, что в этом случае случиться со всем зарегистрированными асинх. операциями.


Ответ на: комментарий от bjorn

Нет. handle_read даже не вызывается когда я закрываю сокет.

Cupper
() автор топика

Если не нужно говорить клиентам «Bye», то можно и stop(), зарегистрироанные операции засохнут. Но это редко подходит для проектов, где нужен graceful shutdown.

Если не сложно, дополни до минимального компилируемого примера, на котором воспроизводится.

ratatosk
()
Ответ на: комментарий от ratatosk

deadlock у меня был, а не проблема с сокетами :(

Cupper
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.