Fix: (move and) make get_thread_id "nil safe"

necessary since native (Java) thread is kept as a weak ref
so un-wrapping should deal with a potentially GCd instance

resolves GH-11450

Fixes #11458
This commit is contained in:
Karol Bucek 2019-12-23 19:05:59 +01:00
parent 32c306f28f
commit fd36783d4f
3 changed files with 26 additions and 9 deletions

View file

@ -35,14 +35,6 @@ module LogStash::Util
Thread.current[:plugin] = plugin
end
def self.get_thread_id(thread)
if RUBY_ENGINE == "jruby"
JRuby.reference(thread).native_thread.id
else
raise Exception.new("Native thread IDs aren't supported outside of JRuby")
end
end
def self.thread_info(thread)
# When the `thread` is dead, `Thread#backtrace` returns `nil`; fall back to an empty array.
backtrace = (thread.backtrace || []).map do |line|
@ -56,7 +48,7 @@ module LogStash::Util
end
{
"thread_id" => get_thread_id(thread),
"thread_id" => get_thread_id(thread), # might be nil for dead threads
"name" => thread[:name],
"plugin" => (thread[:plugin] ? thread[:plugin].debug_info : nil),
"backtrace" => backtrace,

View file

@ -55,6 +55,7 @@ import org.logstash.log.SlowLoggerExt;
import org.logstash.plugins.HooksRegistryExt;
import org.logstash.plugins.PluginFactoryExt;
import org.logstash.plugins.UniversalPluginExt;
import org.logstash.util.UtilExt;
import java.util.stream.Stream;
@ -308,6 +309,7 @@ public final class RubyUtil {
NULL_TIMED_EXECUTION_CLASS.defineAnnotatedMethods(NullMetricExt.NullTimedExecution.class);
NULL_COUNTER_CLASS.defineAnnotatedMethods(NullNamespacedMetricExt.NullCounter.class);
UTIL_MODULE = LOGSTASH_MODULE.defineModuleUnder("Util");
UTIL_MODULE.defineAnnotatedMethods(UtilExt.class);
ABSTRACT_DLQ_WRITER_CLASS = UTIL_MODULE.defineClassUnder(
"AbstractDeadLetterQueueWriterExt", RUBY.getObject(),
ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR

View file

@ -0,0 +1,23 @@
package org.logstash.util;
import org.jruby.RubyThread;
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
@JRubyModule(name = "Util") // LogStash::Util
public class UtilExt {
@JRubyMethod(module = true)
public static IRubyObject get_thread_id(final ThreadContext context, IRubyObject self, IRubyObject thread) {
if (!(thread instanceof RubyThread)) {
throw context.runtime.newTypeError(thread, context.runtime.getThread());
}
final Thread javaThread = ((RubyThread) thread).getNativeThread(); // weak-reference
// even if thread is dead the RubyThread instance might stick around while the Java thread
// instance already could have been garbage collected - let's return nil for dead meat :
return javaThread == null ? context.nil : context.runtime.newFixnum(javaThread.getId());
}
}