logstash-input-unix 3.1.0 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 896c58b0d59a1806706642d094232fd5945bc83b002581c433111fa130e30fe0
4
- data.tar.gz: 6c253bcc1a178711308b1f4dbe4ecf2c249ac10f37404347c273e65be5647658
3
+ metadata.gz: dce11755b6f6a09ad708f79ee8d9e85fb87e0d98bf2aaedb6d47a316e1de6731
4
+ data.tar.gz: 84c73daebb51aa1813b528e42113e1a26f73a5162ced25a8c9043648daf54f14
5
5
  SHA512:
6
- metadata.gz: 1bff9d9ceae1b90c4f6a5edaa4557445f46856704b4b5de6629716222ff3758aa9033ddb0efb484954604ce1d4d2cc78ad87210babeb8abe213e347488b7569b
7
- data.tar.gz: 269752a4d28c40df2c8bec3e7c8149df818f74f46eae44cf3ce3164f69ddaae7bb894655ec24484656e89021f3cf1af22b4d96257fa9a86428e5cc401ec4c02d
6
+ metadata.gz: a259754acac7b218a5f62f6341f981266833a26395f3fd4341fcec6ed1af843d891561937cd7a16a2478863d2bd7a5d61b85dfe62a00b4ee3f340b35f3ce02d6
7
+ data.tar.gz: f85ae87765a0c9ddde40a91d8b4438d4e62d6ec68b1abb187d6c59fa3e643f4ce624656f97a13fd84fde86e85c63021e46f8eafddef1ba05ea8a9557a312b2ca
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 3.1.2
2
+ - Fix: eliminate high CPU usage when data timeout is disabled and no data is available on the socket [#30](https://github.com/logstash-plugins/logstash-input-unix/pull/30)
3
+
4
+ ## 3.1.1
5
+ - Fix: unable to stop plugin (on LS 6.x) [#29](https://github.com/logstash-plugins/logstash-input-unix/pull/29)
6
+ - Refactor: plugin internals got reviewed for `data_timeout => ...` to work reliably
7
+
1
8
  ## 3.1.0
2
9
  - Feat: adjust fields for ECS compatibility [#28](https://github.com/logstash-plugins/logstash-input-unix/pull/28)
3
10
 
@@ -15,8 +15,6 @@ class LogStash::Inputs::Unix < LogStash::Inputs::Base
15
15
 
16
16
  include LogStash::PluginMixins::ECSCompatibilitySupport(:disabled, :v1, :v8 => :v1)
17
17
 
18
- class Interrupted < StandardError; end
19
-
20
18
  config_name "unix"
21
19
 
22
20
  default :codec, "line"
@@ -54,7 +52,6 @@ class LogStash::Inputs::Unix < LogStash::Inputs::Base
54
52
  public
55
53
  def register
56
54
  require "socket"
57
- require "timeout"
58
55
 
59
56
  if server?
60
57
  @logger.info("Starting unix input listener", :address => @path, :force_unlink => @force_unlink)
@@ -87,26 +84,24 @@ class LogStash::Inputs::Unix < LogStash::Inputs::Base
87
84
  begin
88
85
  hostname = Socket.gethostname
89
86
  while !stop?
90
- buf = nil
91
- # NOTE(petef): the timeout only hits after the line is read
92
- # or socket dies
93
- # TODO(sissel): Why do we have a timeout here? What's the point?
94
- if @data_timeout == -1
95
- buf = socket.readpartial(16384)
96
- else
97
- Timeout::timeout(@data_timeout) do
98
- buf = socket.readpartial(16384)
99
- end
87
+ data = io_interruptable_readpartial(socket, 16384, @data_timeout)
88
+
89
+ if data == :data_timeout
90
+ # socket not ready after @data_timeout seconds
91
+ @logger.info("Closing connection after read timeout", :path => @path)
92
+ return
93
+ elsif data == :stopping
94
+ @logger.trace("Shutdown in progress", :path => @path)
95
+ next # let next loop handle graceful stop
100
96
  end
101
- @codec.decode(buf) do |event|
97
+
98
+ @codec.decode(data) do |event|
102
99
  decorate(event)
103
100
  event.set(@host_name_field, hostname) unless event.include?(@host_name_field)
104
101
  event.set(@file_path_field, @path) unless event.include?(@file_path_field)
105
102
  output_queue << event
106
103
  end
107
104
  end
108
- rescue Timeout::Error
109
- @logger.info("Closing connection after read timeout", :path => @path)
110
105
  rescue => e
111
106
  if @logger.debug?
112
107
  @logger.debug("Closing connection", :path => @path, :exception => e, :backtrace => e.backtrace)
@@ -114,7 +109,6 @@ class LogStash::Inputs::Unix < LogStash::Inputs::Base
114
109
  @logger.info("Closing connection", :path => @path, :exception => e)
115
110
  end
116
111
  end
117
-
118
112
  ensure
119
113
  begin
120
114
  socket.close
@@ -123,6 +117,35 @@ class LogStash::Inputs::Unix < LogStash::Inputs::Base
123
117
  end
124
118
  end
125
119
 
120
+ ##
121
+ # Emulates `IO#readpartial` with a timeout and our plugin's stop-condition,
122
+ # limiting blocking calls to windows of 10s or less to ensure it can be interrupted.
123
+ #
124
+ # @param readable_io [IO] the IO to read from
125
+ # @param maxlen [Integer] the max bytes to be read
126
+ # @param timeout [Number] the maximum number of seconds to , or -1 to disable timeouts
127
+ #
128
+ # @return [:data_timeout] if timeout was reached before bytes were available
129
+ # @return [:stopping] if plugin stop-condition was detected before bytes were available
130
+ # @return [String] a non-empty string if bytes became available before the timeout was reached
131
+ def io_interruptable_readpartial(readable_io, maxlen, timeout)
132
+
133
+ data_timeout_deadline = timeout < 0 ? nil : Time.now + timeout
134
+ maximum_blocking_seconds = timeout < 0 || timeout > 10 ? 10 : timeout
135
+
136
+ loop do
137
+ return :stopping if stop?
138
+ result = readable_io.read_nonblock(maxlen, exception: false)
139
+
140
+ return result if result.kind_of?(String)
141
+ raise EOFError if result.nil?
142
+
143
+ return :data_timeout if (data_timeout_deadline && data_timeout_deadline < Time.now)
144
+ IO.select([readable_io], nil, nil, maximum_blocking_seconds)
145
+ end
146
+ end
147
+ private :io_interruptable_readpartial
148
+
126
149
  private
127
150
  def server?
128
151
  @mode == "server"
@@ -141,9 +164,9 @@ class LogStash::Inputs::Unix < LogStash::Inputs::Base
141
164
  end
142
165
  else
143
166
  while !stop?
144
- if File.socket?(@path) then
167
+ if File.socket?(@path)
145
168
  @client_socket = UNIXSocket.new(@path)
146
- @client_socket.instance_eval { class << self; include ::LogStash::Util::SocketPeer end }
169
+ @client_socket.extend ::LogStash::Util::SocketPeer
147
170
  @logger.debug("Opened connection", :client => @path)
148
171
  handle_socket(@client_socket, output_queue)
149
172
  else
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-input-unix'
4
- s.version = '3.1.0'
4
+ s.version = '3.1.2'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Reads events over a UNIX socket"
7
7
  s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
@@ -55,8 +55,29 @@ describe LogStash::Inputs::Unix do
55
55
  end
56
56
 
57
57
  context "when the unix socket has no data to be read" do
58
- it_behaves_like "an interruptible input plugin" do
59
- let(:run_forever) { false }
58
+
59
+ let(:run_forever) { false }
60
+
61
+ it_behaves_like "an interruptible input plugin"
62
+
63
+ context 'with timeout' do
64
+
65
+ let(:config) { super().merge "data_timeout" => 1.0 }
66
+
67
+ let(:queue) { SizedQueue.new(10) }
68
+ before(:each) { subject.register }
69
+ after(:each) { subject.do_stop }
70
+
71
+ it "closes socket after timeout" do
72
+ plugin_thread = Thread.new(subject, queue) { |subject, queue| subject.run(queue) }
73
+ sleep 0.5
74
+ client_socket = subject.instance_variable_get :@client_socket
75
+ expect( client_socket.closed? ).to be false
76
+ sleep 1.0 # allow timeout to kick in
77
+ expect( client_socket.closed? ).to be true
78
+ expect( plugin_thread ).to be_alive
79
+ end
80
+
60
81
  end
61
82
  end
62
83
 
data/spec/spec_helper.rb CHANGED
@@ -12,7 +12,7 @@ class UnixSocketHelper
12
12
  end
13
13
 
14
14
  def new_socket(path)
15
- @path = path
15
+ @path = path
16
16
  File.unlink if File.exists?(path) && File.socket?(path)
17
17
  @socket = UNIXServer.new(path)
18
18
  self
@@ -31,7 +31,6 @@ class UnixSocketHelper
31
31
  end
32
32
 
33
33
  def close
34
- @thread.kill
35
34
  @socket.close
36
35
  File.unlink(path)
37
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-unix
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-22 00:00:00.000000000 Z
11
+ date: 2022-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement