fix some race conditions (#5220)

* fix memory leak

* race condition fixes and change log

* race condition fixes and change log
This commit is contained in:
Ken Stevens 2023-08-21 13:27:44 -04:00 committed by GitHub
parent b9155721a7
commit deeffe2253
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 33 deletions

View File

@ -1177,7 +1177,14 @@ public class FhirContext {
synchronized (this) { synchronized (this) {
if (!myInitialized && !myInitializing) { if (!myInitialized && !myInitializing) {
myInitializing = true; myInitializing = true;
try {
scanResourceTypes(toElementList(myResourceTypesToScan)); scanResourceTypes(toElementList(myResourceTypesToScan));
} catch (Exception e) {
ourLog.error("Failed to initialize FhirContext", e);
throw e;
} finally {
myInitializing = false;
}
} }
} }
} }

View File

@ -270,14 +270,6 @@ public abstract class BaseApp {
// Actually execute the command // Actually execute the command
command.run(parsedOptions); command.run(parsedOptions);
myShutdownHookHasNotRun = true;
runCleanupHookAndUnregister();
if (!HapiSystemProperties.isTestModeEnabled()) {
System.exit(0);
}
} catch (ParseException e) { } catch (ParseException e) {
if (!HapiSystemProperties.isTestModeEnabled()) { if (!HapiSystemProperties.isTestModeEnabled()) {
LogbackUtil.loggingConfigOff(); LogbackUtil.loggingConfigOff();
@ -296,6 +288,13 @@ public abstract class BaseApp {
ourLog.error("Error during execution: ", t); ourLog.error("Error during execution: ", t);
runCleanupHookAndUnregister(); runCleanupHookAndUnregister();
exitDueToException(new CommandFailureException("Error: " + t, t)); exitDueToException(new CommandFailureException("Error: " + t, t));
} finally {
myShutdownHookHasNotRun = true;
runCleanupHookAndUnregister();
if (!HapiSystemProperties.isTestModeEnabled()) {
System.exit(0);
}
} }
} }

View File

@ -75,8 +75,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
/** /**
* Constructor * Constructor
* *
* @param theFhirContext * @param theFhirContext The context
* The context
*/ */
public RestfulClientFactory(FhirContext theFhirContext) { public RestfulClientFactory(FhirContext theFhirContext) {
myContext = theFhirContext; myContext = theFhirContext;
@ -142,13 +141,10 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
/** /**
* Instantiates a new client instance * Instantiates a new client instance
* *
* @param theClientType * @param theClientType The client type, which is an interface type to be instantiated
* The client type, which is an interface type to be instantiated * @param theServerBase The URL of the base for the restful FHIR server to connect to
* @param theServerBase
* The URL of the base for the restful FHIR server to connect to
* @return A newly created client * @return A newly created client
* @throws ConfigurationException * @throws ConfigurationException If the interface type is not an interface
* If the interface type is not an interface
*/ */
@Override @Override
public synchronized <T extends IRestfulClient> T newClient(Class<T> theClientType, String theServerBase) { public synchronized <T extends IRestfulClient> T newClient(Class<T> theClientType, String theServerBase) {
@ -281,13 +277,8 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
break; break;
case ONCE: case ONCE:
if (myValidatedServerBaseUrls.contains(serverBase)) {
break;
}
synchronized (myValidatedServerBaseUrls) { synchronized (myValidatedServerBaseUrls) {
if (!myValidatedServerBaseUrls.contains(serverBase)) { if (myValidatedServerBaseUrls.add(serverBase)) {
myValidatedServerBaseUrls.add(serverBase);
validateServerBase(serverBase, theHttpClient, theClient); validateServerBase(serverBase, theHttpClient, theClient);
} }
} }
@ -396,20 +387,13 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
} }
String serverBase = normalizeBaseUrlForMap(theServerBase); String serverBase = normalizeBaseUrlForMap(theServerBase);
if (myValidatedServerBaseUrls.contains(serverBase)) {
return;
}
synchronized (myValidatedServerBaseUrls) {
myValidatedServerBaseUrls.add(serverBase); myValidatedServerBaseUrls.add(serverBase);
} }
}
/** /**
* Get the http client for the given server base * Get the http client for the given server base
* *
* @param theServerBase * @param theServerBase the server base
* the server base
* @return the http client * @return the http client
*/ */
protected abstract IHttpClient getHttpClient(String theServerBase); protected abstract IHttpClient getHttpClient(String theServerBase);

View File

@ -0,0 +1,7 @@
---
type: fix
issue: 5220
title: "Fixed a race condition in RestfulClientFactory that could cause validateInitialized() to deadlock.
Fixed a race condition in FhirContext initialization that could produce a 'this.myNameToResourceType is null' NPE.
Fixed a shutdown hook memory leak in BaseApp that happened when the command threw an exception;
this memory leak only affects code that calls App.main repeatedly which is probably only in test code."

View File

@ -113,7 +113,7 @@ public class ClientThreadedCapabilitiesTest {
} else { } else {
// metadata request must always be first // metadata request must always be first
if (counter.get() == 0) { if (counter.get() == 0) {
fail("A non-metadata request was executed before metadata request"); fail("A non-metadata request was executed before metadata request: " + theRequest.getUri() + " counter: " + counter.get());
} }
} }
} }