GpgSigner: prevent class lock inversion on the default signer
Don't store the default signer in a static field of the abstract superclass GpgSigner. This many lead to a lock inversion on the class initialization locks if there are concurrent loads of the GpgSigner class and of one of its subclasses, and that subclass happens to be the one the ServiceLoader wants to load. Use the holder pattern to de-couple the loading of class GpgSigner from the ServiceLoader call. Bug: 579550 Change-Id: Ifac0ea0c8985a09fe0518d0dabc072fafd6db907 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
This commit is contained in:
parent
eca101fc05
commit
fbce3122e0
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2018, Salesforce. and others
|
* Copyright (C) 2018, 2022 Salesforce and others
|
||||||
*
|
*
|
||||||
* This program and the accompanying materials are made available under the
|
* This program and the accompanying materials are made available under the
|
||||||
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
||||||
|
@ -26,22 +26,38 @@
|
||||||
* @since 5.3
|
* @since 5.3
|
||||||
*/
|
*/
|
||||||
public abstract class GpgSigner {
|
public abstract class GpgSigner {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(GpgSigner.class);
|
private static final Logger LOG = LoggerFactory.getLogger(GpgSigner.class);
|
||||||
|
|
||||||
private static GpgSigner defaultSigner = loadGpgSigner();
|
private static class DefaultSigner {
|
||||||
|
|
||||||
private static GpgSigner loadGpgSigner() {
|
private static volatile GpgSigner defaultSigner = loadGpgSigner();
|
||||||
try {
|
|
||||||
ServiceLoader<GpgSigner> loader = ServiceLoader
|
private static GpgSigner loadGpgSigner() {
|
||||||
.load(GpgSigner.class);
|
try {
|
||||||
Iterator<GpgSigner> iter = loader.iterator();
|
ServiceLoader<GpgSigner> loader = ServiceLoader
|
||||||
if (iter.hasNext()) {
|
.load(GpgSigner.class);
|
||||||
return iter.next();
|
Iterator<GpgSigner> iter = loader.iterator();
|
||||||
|
if (iter.hasNext()) {
|
||||||
|
return iter.next();
|
||||||
|
}
|
||||||
|
} catch (ServiceConfigurationError e) {
|
||||||
|
LOG.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
} catch (ServiceConfigurationError e) {
|
return null;
|
||||||
LOG.error(e.getMessage(), e);
|
}
|
||||||
|
|
||||||
|
private DefaultSigner() {
|
||||||
|
// No instantiation
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GpgSigner getDefault() {
|
||||||
|
return defaultSigner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefault(GpgSigner signer) {
|
||||||
|
defaultSigner = signer;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,7 +66,7 @@ private static GpgSigner loadGpgSigner() {
|
||||||
* @return the default signer, or <code>null</code>.
|
* @return the default signer, or <code>null</code>.
|
||||||
*/
|
*/
|
||||||
public static GpgSigner getDefault() {
|
public static GpgSigner getDefault() {
|
||||||
return defaultSigner;
|
return DefaultSigner.getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,7 +77,7 @@ public static GpgSigner getDefault() {
|
||||||
* default.
|
* default.
|
||||||
*/
|
*/
|
||||||
public static void setDefault(GpgSigner signer) {
|
public static void setDefault(GpgSigner signer) {
|
||||||
GpgSigner.defaultSigner = signer;
|
DefaultSigner.setDefault(signer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue