[ 
https://issues.apache.org/jira/browse/HADOOP-14195?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15930484#comment-15930484
 ] 

John Zhuge commented on HADOOP-14195:
-------------------------------------

More and more applications start to access cloud filesystem directly using URI 
{{s3a://}} or {{adl://}}. {{Configuration.getPassword}} is called during 
construction of each fs instance to get credentials, thus more likely in 
multiple threads. {{Configuration.getPassword}} uses service loader to load 
credential providers. 

Here is a real-world Hive exception backtrace:
{noformat}
Caused by: java.util.NoSuchElementException
        at sun.misc.CompoundEnumeration.nextElement(CompoundEnumeration.java:59)
        at 
java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:357)
        at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:393)
        at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:474)
        at 
org.apache.hadoop.security.alias.CredentialProviderFactory.getProviders(CredentialProviderFactory.java:57)
        at 
org.apache.hadoop.conf.Configuration.getPasswordFromCredentialProviders(Configuration.java:1950)
        at 
org.apache.hadoop.conf.Configuration.getPassword(Configuration.java:1930)
        at 
org.apache.hadoop.fs.s3a.S3AFileSystem.getAWSAccessKeys(S3AFileSystem.java:374)
        at 
org.apache.hadoop.fs.s3a.S3AFileSystem.initialize(S3AFileSystem.java:175)
        at 
org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2696)
        at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:94)
        at 
org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2733)
        at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2715)
        at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:382)
        at org.apache.hadoop.fs.Path.getFileSystem(Path.java:296)
        at 
parquet.hadoop.ParquetFileReader.readFooter(ParquetFileReader.java:385)
        at 
parquet.hadoop.ParquetFileReader.readFooter(ParquetFileReader.java:372)
        at 
org.apache.hadoop.hive.ql.io.parquet.read.ParquetRecordReaderWrapper.getSplit(ParquetRecordReaderWrapper.java:252)
        at 
org.apache.hadoop.hive.ql.io.parquet.read.ParquetRecordReaderWrapper.<init>(ParquetRecordReaderWrapper.java:95)
        at 
org.apache.hadoop.hive.ql.io.parquet.read.ParquetRecordReaderWrapper.<init>(ParquetRecordReaderWrapper.java:81)
        at 
org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat.getRecordReader(MapredParquetInputFormat.java:72)
        at 
org.apache.hadoop.hive.ql.io.CombineHiveRecordReader.<init>(CombineHiveRecordReader.java:67)
{noformat}

SLIDER-888 reported a similar issue.

So somewhere along the stack, we need to serialize the call.

> CredentialProviderFactory is not thread-safe
> --------------------------------------------
>
>                 Key: HADOOP-14195
>                 URL: https://issues.apache.org/jira/browse/HADOOP-14195
>             Project: Hadoop Common
>          Issue Type: Bug
>          Components: security
>    Affects Versions: 2.7.0
>            Reporter: Vihang Karajgaonkar
>            Assignee: John Zhuge
>         Attachments: TestCredentialProvider.java
>
>
> Multi-threaded access to CredentialProviderFactory is not thread-safe because 
> {{java.util.ServiceLoader}} is not thread-safe (as noted in its Java doc). 
> Thanks to [~jzhuge] I was able to reproduce this issue but creating a simple 
> multi-threaded application which executes the following code in parallel.
> {code:java}
> for (int i = 0; i < ITEMS; i++) {
>           futures.add(executor.submit(new Callable<Void>() {
>               @Override
>               public Void call() throws Exception {
>                   boolean found = false;
>                   for (CredentialProviderFactory factory : serviceLoader) {
>                       CredentialProvider kp = factory.createProvider(uri, 
> conf);
>                       if (kp != null) {
>                           result.add(kp);
>                           found = true;
>                           break;
>                       }
>                   }
>                   if (!found) {
>                       throw new IOException(Thread.currentThread() + "No 
> CredentialProviderFactory for " + uri);
>                   } else {
>                       System.out.println(Thread.currentThread().getName() + " 
> found credentialProvider for " + path);
>                   }
>                   return null;
>               }
>           }));
>       }
> {code}
> I see the following exception trace when I execute the above code.
> {code:java}
> java.util.concurrent.ExecutionException: java.util.NoSuchElementException
>       at java.util.concurrent.FutureTask.report(FutureTask.java:122)
>       at java.util.concurrent.FutureTask.get(FutureTask.java:192)
>       at TestCredentialProvider.main(TestCredentialProvider.java:58)
> Caused by: java.util.NoSuchElementException
>       at java.net.URLClassLoader$3.nextElement(URLClassLoader.java:615)
>       at java.net.URLClassLoader$3.nextElement(URLClassLoader.java:590)
>       at sun.misc.CompoundEnumeration.nextElement(CompoundEnumeration.java:61)
>       at 
> java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:357)
>       at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:393)
>       at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:474)
>       at TestCredentialProvider$1.call(TestCredentialProvider.java:38)
>       at TestCredentialProvider$1.call(TestCredentialProvider.java:1)
>       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
>       at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
>       at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
>       at java.lang.Thread.run(Thread.java:745)
> {code}
> I also see a NPE sometimes 
> {code:java}
> java.util.concurrent.ExecutionException: java.lang.NullPointerException
>       at java.util.concurrent.FutureTask.report(FutureTask.java:122)
>       at java.util.concurrent.FutureTask.get(FutureTask.java:192)
>       at TestCredentialProvider.main(TestCredentialProvider.java:58)
> Caused by: java.lang.NullPointerException
>       at java.util.ServiceLoader.parse(ServiceLoader.java:304)
>       at java.util.ServiceLoader.access$200(ServiceLoader.java:185)
>       at 
> java.util.ServiceLoader$LazyIterator.hasNextService(ServiceLoader.java:357)
>       at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:393)
>       at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:474)
>       at TestCredentialProvider$1.call(TestCredentialProvider.java:38)
>       at TestCredentialProvider$1.call(TestCredentialProvider.java:1)
>       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
>       at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
>       at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
>       at java.lang.Thread.run(Thread.java:745)
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

---------------------------------------------------------------------
To unsubscribe, e-mail: common-issues-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-issues-h...@hadoop.apache.org

Reply via email to