-
Notifications
You must be signed in to change notification settings - Fork 199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix thread leak #568
Fix thread leak #568
Conversation
added thread name to loggers. registered CdsProfileFetcher to be shutdown by sdk mechanism. upgraded to Servlet 3.0.1 spec. Added listener to trigger shutdown during undeploy. added undeploy.sh so tests can be written for this scenario.
increased the number of lines to tail from 25 to 50. added option to specify a different log file. added usage on error from tail command.
change 'ADD' directive to use wildcard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@littleaj one general comment which applies to all Atomic Integer variables. Why should they not be static? I believe they should be shared across different instance of classes so that ThreadId values do not get duplicated. Apart from this left other comments.
@@ -37,13 +37,14 @@ | |||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a fundamental question. Since we are internally using Apache HTTP Client 4.5.3 to send the data, why do we need this sender in the first place? I think if there is anywhere still we are using HTTP Client 4.2 we should remove those. For eg ApacheSenderFactory
looks for old jar on the class path and creates an instance of ApacheSender42. I think we do not need it at all. @littleaj can you take a look as a part of this improvements and trim the unnecessary code there ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's something we can address separately. If it's worth exploring, we should file an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please file an issue to keep an eye on. We can then close if not needed.
private SDKShutdownThread getShutdownThread() { | ||
if (shutdownThread == null) { | ||
private SDKShutdownAction getShutdownAction() { | ||
if (shutdownAction == null) { | ||
synchronized (this) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@littleaj As a one cent advise, I would prefer to start a practice of using Reentrant Lock
instead of synchronizing on this
. There are numerous benefits . I would like everyone to go over.
https://stackoverflow.com/questions/11821801/why-use-a-reentrantlock-if-one-can-use-synchronizedthis
Also it is much more cleaner and less prone to errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any benefits of using RentrantLock
. IMO, Java's lock classes are much less readable and harder to debug, but I'm happy to evaluate some evidence why synchronized
is inadequate for this case.
However, (quoting the best answer from the linked stackoverflow article):
... use it when you actually need something it provides that synchronized doesn't ... but remember that the vast majority of synchronized blocks hardly ever exhibit any contention, let alone high contention. I would advise developing with synchronization until synchronization has proven to be inadequate, rather than simply assuming "the performance will be better" if you use ReentrantLock. Remember, these are advanced tools for advanced users. (And truly advanced users tend to prefer the simplest tools they can find until they're convinced the simple tools are inadequate.) ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I have no objections. I personally feel writing synchronized is two step process whereas reentrant lock just makes it more readable and easy.
@@ -36,7 +36,7 @@ dependencies { | |||
compile ([group: 'org.apache.httpcomponents', name: 'httpasyncclient', version: '4.1.3']) | |||
provided 'com.opensymphony:xwork:2.0.4' // Struts 2 | |||
provided 'org.springframework:spring-webmvc:3.1.0.RELEASE' | |||
provided group: 'javax.servlet', name: 'servlet-api', version: '2.5' | |||
provided group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make sure to register this on OSS before merging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pending review
import org.apache.http.ParseException; | ||
|
||
/** | ||
* Retrieves the application profile from storage | ||
*/ | ||
public interface AppProfileFetcher { | ||
public interface AppProfileFetcher extends Closeable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this @littleaj could you please confirm if this doesn't break spring boot scenario. Specifically I would like to see that with this change do we still need to register the Bean for WebRequestTrackingFilter or the framework can automatically pick it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I'll see what I can find out.
@@ -39,7 +46,7 @@ | |||
|
|||
public class CdsProfileFetcher implements AppProfileFetcher { | |||
|
|||
private HttpAsyncClient httpClient; | |||
private CloseableHttpAsyncClient httpClient; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why shouldn't this variable be final? Do we ever need to do multiple initialization for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The setter is public
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure in this case it cannot be fine but atleast @littleaj the setter can be set to package private (aka default access). This setter is only used in CdsProfileFetcherTests.java which resides in the same package. I know this is not part of your PR but it's good if we can address if possible in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dhaval24 I don't think we can reduce the visibility of a public method in a public class w/o going through the deprecation procedure.
@dhaval24 Regarding your comment about |
@littleaj yes it doesn't appear to have the multiple instances of the classes, but there is no restriction in code base that it would prevent a developer to make that mistake in the future. Either we should add those restrictions on make sure that ThreadIds you are providing are unique always. May be the logic you added in your recent commit will ensure that. |
@dhaval24 The instance identifier does ensure the pools won't have colliding IDs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@littleaj I verified your changes for the SpringBoot Scenario. We would no longer need to specify FilterRegistrationBean and Bean for WebRequestTrackingFilter. Instead with this change the user will have to annotate the SpringBoot main class with @ServletComponentScan("com.microsoft.applicationinsights.web.internal")
tag so that Spring auto configuration can pick up the filter from the Microsoft package. Also the current users who used the bean registration users won't get affected (i.e broken) if they update the library. Both the methods should work fine. Please make sure to update the SpringBoot Documentation to include the same.
PS: SpringBoot needs this additional tag to pick up the Servlet annotations because of embedded servlet containers it uses.
@littleaj really sorry for the later reply. But I found an issue with SpringBoot.I was experimenting more with this and when I instrumented it with Agent I found that we won't be able to use the parameterized constructor in web request tracking filter to bind the name to the filter. Therefore, this won't eliminate creating the two beans I mentioned in my above comment, but would be mandatory. This won't block your PR though, just there would be no advantage in case of SpringBoot. Apologies again. |
Fix #513 .
NOTE: This fix changes the lowest version of the Servet API we support from 2.5 to 3.0!
Here's the gist of the issue:
Here's how I fixed it:
Here's some other things you'll find in this PR:
For significant contributions please make sure you have completed the following items: