Skip to content

Commit 11e69f2

Browse files
authored
server plugin helper: ensure to close all connections at shutdown (#5026)
**Which issue(s) this PR fixes**: Fixes # **What this PR does / why we need it**: TCP server with `server` helper does not close all connections at shutdown process. When receiving data from multiple clients, the server receive the data continuously because the connection is not closed. The server will shut down properly by this PR ### Reproduce 1. Launch Fluentd with following config file. 2. Send syslog data from two or more clients using following client script 3. Terminate Fluentd 4. Relaunch Fluentd, then it shows the `2025-07-16 14:12:26 +0900 [warn]: #0 restoring buffer file: path = xxxxxxxxx` in logs. * config ``` <source> @type syslog tag system <transport tcp> </transport> bind 0.0.0.0 port 5140 </source> <match **> @type file path "#{File.expand_path('~/tmp/fluentd/maillog')}" <buffer> @type file path "#{File.expand_path('~/tmp/fluentd/buffer/buffer_syslog_maillog')}" flush_at_shutdown true </buffer> </match> ``` * client script ```ruby require 'bundler/inline' gemfile do source 'https://rubygems.org' gem 'remote_syslog_sender' end def create_client Thread.new do sender = RemoteSyslogSender.new('127.0.0.1', 5140, protocol: :tcp) loop do sender.transmit("message body") sleep 0.5 end end end clients = [] 3.times do clients << create_client end clients.each(&:join) ``` Example code. ``` @ary = [1,2,3] # It would like 1, 2, and 3 to be processed. # However, following code handles 1 and 3. @ary.each do |i| puts i @ary.delete(i) end ``` **Docs Changes**: Not needed. **Release Note**: Same as the title. Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
1 parent 13cf042 commit 11e69f2

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

lib/fluent/plugin_helper/server.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,10 @@ def stop
356356
end
357357

358358
def shutdown
359-
@_server_connections.each do |conn|
359+
# When it invokes conn.cose, it reduces elements in @_server_connections by close_callback,
360+
# and it reduces the number of loops. This prevents the connection closing.
361+
# So, it requires invoking #dup to avoid the problem.
362+
@_server_connections.dup.each do |conn|
360363
conn.close rescue nil
361364
end
362365

test/plugin_helper/test_server.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,25 @@ class Dummy < Fluent::Plugin::TestBase
381381
d2.stop; d2.before_shutdown; d2.shutdown; d2.after_shutdown; d2.close; d2.terminate
382382
end
383383
end
384+
385+
test 'close all connections by shutdown' do
386+
@d.server_create_tcp(:s, @port) do |data, conn|
387+
end
388+
389+
client_sockets = []
390+
5.times do
391+
client_sockets << TCPSocket.open("127.0.0.1", @port)
392+
end
393+
waiting(4){ sleep 0.1 until @d.instance_variable_get(:@_server_connections).size == 5 }
394+
395+
@d.stop
396+
@d.before_shutdown
397+
@d.shutdown
398+
399+
assert_true @d.instance_variable_get(:@_server_connections).empty?
400+
ensure
401+
client_sockets.each(&:close)
402+
end
384403
end
385404

386405
sub_test_case '#server_create' do

0 commit comments

Comments
 (0)