logstash-input-unix 3.1.0 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
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