[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-bugs] #32194 [Metrics/Library]: NetworkStatusEntryImpl#parseSLine (and probably other methods) is not thread-safe
#32194: NetworkStatusEntryImpl#parseSLine (and probably other methods) is not
thread-safe
---------------------------------+--------------------------
Reporter: karsten | Owner: metrics-team
Type: defect | Status: new
Priority: High | Milestone:
Component: Metrics/Library | Version:
Severity: Normal | Keywords:
Actual Points: | Parent ID:
Points: | Reviewer:
Sponsor: |
---------------------------------+--------------------------
Turns out that creating multiple `DescriptorReader` instances in separate
threads can cause thread-safety issues in
`NetworkStatusEntryImpl#parseSLine`:
{{{
18:02:24.650 [Thread-1] INFO
org.torproject.descriptor.DescriptorSourceFactory - Serving implementation
org.torproject.descriptor.impl.DescriptorReaderImpl for descriptor.reader.
18:02:24.650 [Thread-5] INFO
org.torproject.descriptor.DescriptorSourceFactory - Serving implementation
org.torproject.descriptor.impl.DescriptorReaderImpl for descriptor.reader.
18:02:24.650 [Thread-3] INFO
org.torproject.descriptor.DescriptorSourceFactory - Serving implementation
org.torproject.descriptor.impl.DescriptorReaderImpl for descriptor.reader.
18:02:24.947 [Thread-10] ERROR
org.torproject.descriptor.impl.DescriptorReaderImpl - Bug: uncaught
exception or error while reading descriptors.
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at
org.torproject.descriptor.impl.DescriptorParserImpl.parseOneDescriptor(DescriptorParserImpl.java:236)
at
org.torproject.descriptor.impl.DescriptorParserImpl.parseOneOrMoreDescriptors(DescriptorParserImpl.java:213)
at
org.torproject.descriptor.impl.DescriptorParserImpl.detectTypeAndParseDescriptors(DescriptorParserImpl.java:61)
at
org.torproject.descriptor.impl.DescriptorParserImpl.parseDescriptors(DescriptorParserImpl.java:33)
at
org.torproject.descriptor.impl.DescriptorReaderImpl$DescriptorReaderRunnable.readTarball(DescriptorReaderImpl.java:320)
at
org.torproject.descriptor.impl.DescriptorReaderImpl$DescriptorReaderRunnable.readTarballs(DescriptorReaderImpl.java:270)
at
org.torproject.descriptor.impl.DescriptorReaderImpl$DescriptorReaderRunnable.run(DescriptorReaderImpl.java:161)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)
at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at
org.torproject.descriptor.impl.DescriptorParserImpl.parseOneDescriptor(DescriptorParserImpl.java:229)
... 7 common frames omitted
Caused by: java.lang.NullPointerException: null
at
org.torproject.descriptor.impl.NetworkStatusEntryImpl.parseSLine(NetworkStatusEntryImpl.java:177)
at
org.torproject.descriptor.impl.NetworkStatusEntryImpl.parseStatusEntryBytes(NetworkStatusEntryImpl.java:98)
at
org.torproject.descriptor.impl.NetworkStatusEntryImpl.<init>(NetworkStatusEntryImpl.java:58)
at
org.torproject.descriptor.impl.RelayNetworkStatusConsensusImpl.parseStatusEntry(RelayNetworkStatusConsensusImpl.java:121)
at
org.torproject.descriptor.impl.NetworkStatusImpl.parseStatusEntries(NetworkStatusImpl.java:85)
at
org.torproject.descriptor.impl.NetworkStatusImpl.splitAndParseParts(NetworkStatusImpl.java:59)
at
org.torproject.descriptor.impl.NetworkStatusImpl.<init>(NetworkStatusImpl.java:27)
at
org.torproject.descriptor.impl.RelayNetworkStatusConsensusImpl.<init>(RelayNetworkStatusConsensusImpl.java:28)
... 12 common frames omitted
18:02:24.948 [Thread-1] INFO
org.torproject.descriptor.DescriptorSourceFactory - Serving implementation
org.torproject.descriptor.impl.DescriptorReaderImpl for descriptor.reader.
}}}
Code to reproduce this in 1 out of 10 cases:
{{{
import org.torproject.descriptor.Descriptor;
import org.torproject.descriptor.DescriptorSourceFactory;
import org.torproject.descriptor.RelayNetworkStatusConsensus;
import java.io.File;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(15,
(Runnable r) -> {
Thread t = new Thread(r);
//t.setDaemon(true);
return t;
});
SortedSet<File> descriptorFiles = new TreeSet<>();
for (File descriptorFile : new File("in").listFiles()) {
descriptorFiles.add(descriptorFile);
}
for (int i = 0; i < 5; i++) {
for (File descriptorFile : descriptorFiles) {
Thread readerThread = new Thread() {
@Override
public void run() {
parseDescriptorFile(descriptorFile);
}
};
executor.submit(readerThread);
}
}
}
private static void parseDescriptorFile(File descriptorFile) {
for (Descriptor descriptor
: DescriptorSourceFactory.createDescriptorReader()
.readDescriptors(descriptorFile)) {
// ignore
if (descriptor instanceof RelayNetworkStatusConsensus) {
continue;
}
}
}
}
}}}
There are probably similar issues with other methods.
--
Ticket URL: <https://trac.torproject.org/projects/tor/ticket/32194>
Tor Bug Tracker & Wiki <https://trac.torproject.org/>
The Tor Project: anonymity online
_______________________________________________
tor-bugs mailing list
tor-bugs@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-bugs