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
Inconsistent synchronization causes sporadic NPEs #1568
Comments
HI @bvremme Thanks for writing up this issue. It's unfortunate that you are not able to write up a PR to fix this. Thank you also for the LockServiceFactoryTest testcase. We will take a look and add it to our list of issues. |
Thanks @molivasdat, As for most threading issues, it is hard to write consistently failing tests, 'numbers game' tests as the one above can help. Slow, but requires little wiring. |
Thanks @bvremmeinfor, I brought your test and fix into #1991 and they work great. I appreciate the test |
Fixed by #1991 |
Nice! Thank you @nvoxland :-) |
This was fixed with #1991 in 4.5.0 |
Environment
Liquibase Version:
3.8.x all the way to latest
Liquibase Integration & Version:
Plain Java API
Liquibase Extension(s) & Version:
None
Database Vendor & Version:
Any
Operating System Type & Version:
Any
Description
Inconsistent synchronization in LockServiceFactory & ChangeLogHistoryServiceFactory causes sporadic null pointer exceptions in multi-threaded environments.
Static 'instance' variable can be set to null in resetAll(), resulting in null value from getInstance() as they synchronize on different objects (static class vs instance).
Instance modified, synchronized on this (instance) not class as in getInstance():
liquibase/liquibase-core/src/main/java/liquibase/lockservice/LockServiceFactory.java
Line 91 in 03c187a
Instance modified, synchronized on this (instance) not class as in getInstance():
liquibase/liquibase-core/src/main/java/liquibase/changelog/ChangeLogHistoryServiceFactory.java
Line 99 in 03c187a
Typicall locations (3.8.0):
Caused by: java.lang.NullPointerException
at liquibase.Liquibase.checkLiquibaseTables(Liquibase.java:1231)
at liquibase.Liquibase.update(Liquibase.java:193)
at liquibase.Liquibase.update(Liquibase.java:179)
Caused by: java.lang.NullPointerException
at liquibase.Liquibase.resetServices(Liquibase.java:1138)
at liquibase.Liquibase.update(Liquibase.java:210)
at liquibase.Liquibase.update(Liquibase.java:179)
Caused by: java.lang.NullPointerException
at liquibase.Liquibase.resetServices(Liquibase.java:1137)
at liquibase.Liquibase.update(Liquibase.java:210)
at liquibase.Liquibase.update(Liquibase.java:179)
Caused by: java.lang.NullPointerException
at liquibase.Liquibase.update(Liquibase.java:183)
at liquibase.Liquibase.update(Liquibase.java:179)
Steps To Reproduce
Issue is very timing sensitive, in most cases it works, a little patience is required.
12 threads usually fail in less than 400 iterations on my machine (12 cores).
Getting the threads to interleave increases the chance.
It can be hard to reproduce, but once you've seen it you can't unsee it.
Alternative: Unit-test, see sample for LockServiceFactoryTest below
Actual Behavior
Occasional null pointer exceptions in multi-threaded environment.
Expected/Desired Behavior
Databases upgraded without errors.
Screenshots (if appropriate)
N/A
Additional Context
I don't have a PR, because that would require approval from legal and that is out of scope, but a simple fix is:
Keep up the good work 👍
Sample LockServiceFactoryTest for inspiration:
The text was updated successfully, but these errors were encountered: