-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Deadlock when loading DataType classes #3777
Comments
Thank you very much for letting us know. Yes, this can indeed happen, specifically because of the static block in static {
// Load all dialect-specific data types
// TODO [#650] Make this more reliable using a data type registry
try {
Class.forName(CUBRIDDataType.class.getName());
Class.forName(DerbyDataType.class.getName());
Class.forName(FirebirdDataType.class.getName());
Class.forName(H2DataType.class.getName());
Class.forName(HSQLDBDataType.class.getName());
Class.forName(MariaDBDataType.class.getName());
Class.forName(MySQLDataType.class.getName());
Class.forName(PostgresDataType.class.getName());
Class.forName(SQLiteDataType.class.getName());
} catch (Exception ignore) {}
} Before we look into fixing this, could you tell me why this might happen in your specific use-case? Do you have generated classes that refer to the dialect-specific data types early on? |
We have some helper classes that are initialized early on and refer to the DataType classes, we're not using generated classes. We also use multiple database types at the same time in different threads in the jvm. Our fix is to load jooq separately for each thread since they already had their own class loaders. I imagine our situation is not very common, but we wanted to let you know. |
Yes, it's not very common, but I guess we were taking bets when we implemented the above, and Murphy's law (as always) struck. In fact, we knew that it would strike (see #2322), but we couldn't think of a scenario to produce that issue... Thanks for letting us know about this. We'll think of a fix that'll make initialisation more robust. |
Related #2322 |
I've found two possible solutions:
The latter would be much more robust in the sense of #2322. But I think it won't make it into 3.5.0 anymore. It'll need some more thinking. |
We have also run into this issue. We worked around it by running this little code block on the applications main thread before starting up other threads:
|
@gundeman: Thank you very much for documenting this |
We happened to bump into this issue and while digging a bit into it I was wondering why the initialization lines in
Unless I'm mistaken I believe it's an overkill - as soon as the code mentions
etc. and the deadlock no longer occurs. |
Thanks, @victorbr. Interesting thoughts. Since these deadlock occurred, there certainly had been quite a few changes to jOOQ's internals. I'll investigate your suggestion, soon. |
Just to clarify - this is easily reproducible on 3.10.0 with a test as simple as
(the original test in this thread, simplified) |
Thanks for the additional heads-up |
Yeah, well about that suggestion:
Try running this at the end of your main method: System.out.println(DSL.using(SQLDialect.MYSQL).render(cast(field("x"), SQLDataType.VARCHAR(6)))); Unfortunately, referencing the class doesn't necessarily load it. And if you did anything like referencing a member of the class, such as It's really a tricky problem to solve. I suspect it can only be solved like this: #5713, i.e. by getting rid of the internal static caches in |
Not sure I got this. With my version (referencing
With 3.10.0 it prints
|
Yeah, well the point is, |
Aha! I see! Though I'm kinda puzzled by the current state - there's a clear circular dependency between |
Yes, there's a circular dependency, which isn't a problem if only one thread loads the classes:
This is a hack that persisted from early days on, and it works quite well in most cases. Every now and then, someone runs into this and the workaround is always to pre-initialise the data types. This is not a nice situation of course, and it does need fixing. |
The main reason for this deadlock to happen is because end user code references This seems to be the most reliable way to prevent these deadlocks without implementing the rather difficult change #5713. |
We'll consider this issue fixed through the deprecation of the offending "internal" API: #7375. If it re-appears in other contexts, we can reopen this issue. |
@lukaseder I don't understand what the replacement for the deprecated class is, i.e. we are using org.jooq.util.postgres.PostgresDataType#TEXT, what should I replace this with in our code? In general, it is really helpful when deprecating something to also mention what the new replacement is. |
You should reference
The corresponding
Yes, I'm well aware of this "best practice", thanks for mentioning this. I'll fix the Javadoc of the |
Thanks for the insights, @lukaseder. |
sorry for bumping this dead post, any idea what's an equivalent for postgres DOUBLE PRECISION (float8) ? |
@raulvc May I ask you to create a new issue with more details? https://github.com/jOOQ/jOOQ/issues/new/choose |
@lukaseder I'm using JOOQ only for migrations (with Flyway), so I would like to have the exact PostgreSQL data types when I create the tables (instead of the SQL equivalents). Just as an example, if I add a column with type If we want to keep PostgreSQL specific data types, what should we do? 🤔 |
In general, please use a data type binding and attach that to the code generator's output: However, I think that it's currently not possible (without resorting to string manipulation) to override the data type literal when generating DDL statements. |
I see 🤔 as I'm using it for migrations only, my best options is to go back to plain SQL files. However, thank you for the quick response on closed issue @lukaseder! 🙂 |
We're seeing a deadlock when two different threads load different DataType classes at the same time. It looks like loading one DataType class causes the others to be loaded as well during class initialization. But, this can cause a deadlock when multiple threads are trying to load these DataType classes because they each hold a lock on the class and end up waiting for the others to finish.
The following code reproduces the deadlock for me:
Here is a stack dump from after the deadlock happens:
The text was updated successfully, but these errors were encountered: