mirror of
				https://github.com/pocoproject/poco.git
				synced 2025-11-04 12:17:37 +01:00 
			
		
		
		
	fix(SocketReactor): Protect stop() and wakeUp() from reentrance #4217
This commit is contained in:
		@@ -160,13 +160,14 @@ void SocketReactor::sleep()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void SocketReactor::stop()
 | 
					void SocketReactor::stop()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	_stop = true;
 | 
						if (_stop.exchange(true)) return;
 | 
				
			||||||
	wakeUp();
 | 
						wakeUp();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SocketReactor::wakeUp()
 | 
					void SocketReactor::wakeUp()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (_stop) return;
 | 
				
			||||||
	_pollSet.wakeUp();
 | 
						_pollSet.wakeUp();
 | 
				
			||||||
	_event.set();
 | 
						_event.set();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -395,6 +395,45 @@ namespace
 | 
				
			|||||||
			Poco::Thread::sleep(500);
 | 
								Poco::Thread::sleep(500);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class DummyServiceHandler
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							DummyServiceHandler(StreamSocket& socket, SocketReactor& reactor) : _socket(socket),
 | 
				
			||||||
 | 
								_reactor(reactor)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								_reactor.addEventHandler(_socket, Observer<DummyServiceHandler, ReadableNotification>(*this, &DummyServiceHandler::onReadable));
 | 
				
			||||||
 | 
								_reactor.addEventHandler(_socket, Observer<DummyServiceHandler, ShutdownNotification>(*this, &DummyServiceHandler::onShutdown));
 | 
				
			||||||
 | 
								_socket.setBlocking(false);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							~DummyServiceHandler()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								_reactor.removeEventHandler(_socket, Observer<DummyServiceHandler, ReadableNotification>(*this, &DummyServiceHandler::onReadable));
 | 
				
			||||||
 | 
								_reactor.removeEventHandler(_socket, Observer<DummyServiceHandler, ShutdownNotification>(*this, &DummyServiceHandler::onShutdown));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void onReadable(ReadableNotification* pNf)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								pNf->release();
 | 
				
			||||||
 | 
								char buffer[64];
 | 
				
			||||||
 | 
								do
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (0 == _socket.receiveBytes(&buffer[0], sizeof(buffer)))
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
								} while (true);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void onShutdown(ShutdownNotification* pNf)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								pNf->release();
 | 
				
			||||||
 | 
								delete this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							StreamSocket   _socket;
 | 
				
			||||||
 | 
							SocketReactor& _reactor;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -589,19 +628,40 @@ void SocketReactorTest::testDataCollection()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void SocketReactorTest::testSocketConnectorDeadlock()
 | 
					void SocketReactorTest::testSocketConnectorDeadlock()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	SocketAddress ssa;
 | 
						{
 | 
				
			||||||
	ServerSocket ss(ssa);
 | 
							SocketAddress ssa;
 | 
				
			||||||
	SocketAddress sa("127.0.0.1", ss.address().port());
 | 
							ServerSocket ss(ssa);
 | 
				
			||||||
	SocketReactor reactor;
 | 
							SocketAddress sa("127.0.0.1", ss.address().port());
 | 
				
			||||||
	Thread thread;
 | 
							SocketReactor reactor;
 | 
				
			||||||
 | 
							Thread thread;
 | 
				
			||||||
 | 
							int i = 0;
 | 
				
			||||||
 | 
							while (++i < 10)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto sc = new SocketConnector<SleepClientServiceHandler>(sa, reactor);
 | 
				
			||||||
 | 
								thread.startFunc([&reactor]() { reactor.run(); });
 | 
				
			||||||
 | 
								reactor.stop();
 | 
				
			||||||
 | 
								thread.join();
 | 
				
			||||||
 | 
								delete sc;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int i = 0;
 | 
						int i = 0;
 | 
				
			||||||
	while (++i < 10)
 | 
						while (++i < 10)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto sc = new SocketConnector<SleepClientServiceHandler>(sa, reactor);
 | 
							SocketAddress ssa;
 | 
				
			||||||
		thread.startFunc([&reactor]() { reactor.run(); });
 | 
							ServerSocket ss(ssa);
 | 
				
			||||||
 | 
							SocketReactor reactor;
 | 
				
			||||||
 | 
							SocketAcceptor<DummyServiceHandler> acceptor(ss, reactor);
 | 
				
			||||||
 | 
							Thread thread;
 | 
				
			||||||
 | 
							thread.start(reactor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							SocketAddress sa("127.0.0.1", ss.address().port());
 | 
				
			||||||
 | 
							StreamSocket sock(sa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string data("HELLO");
 | 
				
			||||||
 | 
							sock.sendBytes(data.data(), static_cast<int>(data.size()));
 | 
				
			||||||
		reactor.stop();
 | 
							reactor.stop();
 | 
				
			||||||
		thread.join();
 | 
							thread.join();
 | 
				
			||||||
		delete sc;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user