You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PostgreSQL processes remain running after JabRef crashes or is forcefully terminated #12844
Latest development branch build (please note build date below)
Operating system
Windows
Details on version and operating system
Windows 10
Checked with the latest development build (copy version output from About dialog)
I made a backup of my libraries before testing the latest development version.
I have tested the latest development version and the problem persists
Steps to reproduce the behaviour
When JabRef crashes or is forcefully terminated (e.g., via kill -9 or Task Manager), associated PostgreSQL processes often remain running. These orphaned processes continue to consume system resources unnecessarily.
Steps to Reproduce
Start JabRef with a PostgreSQL backend.
Forcefully terminate JabRef (e.g., using kill -9 or Task Manager).
Open Task Manager (Windows) or use ps on Linux/macOS.
Observe that multiple PostgreSQL Server processes are still running.
Expected Behavior
All PostgreSQL-related processes spawned by JabRef should terminate when JabRef is unexpectedly closed.
Actual Behavior
PostgreSQL processes persist after JabRef exits unexpectedly, leading to orphaned background processes.
Appendix
Screenshot
Screenshot shows several idle PostgreSQL Server processes still running after JabRef was terminated.
I have faced this too (noticed this yesterday). Every time I close and re-run JabRef (when running via IntelliJ), my task manager shows the old Postgres instance running. On running a new JabRef session again, a new Postgres session is also launched. After 5-6 trials, I was wondering why my system was lagging so much, then checked the task manager which had 6 running postgres instances.
Edit - what I meant was another implication of this is lag during development.
On checking logs, neither the try nor the catch is executed. On reading more, it appears that it's because there is no way to reliably execute code in case of a SIGKILL (the shutdownhook helps in case of SIGTERM and SIGINT).
I am thinking whether handling SIGKILL is something a software should (or can) make behavioral guarantees about, since control can no longer be in hands of it.
For crashes - i think we should look at the reason. Only if caused due to something going wrong in jabref, we should fix that.
For forceful termination - again, that is not an intended way to use JabRef.
If there was a way to handle sigkill gracefully, we would. But until then, and in one perspective, this issue seems to be intended behavior.
Reusing postgres instances should be a separate issue, and this IMO could be closed. @koppor we need to add to devdocs not to use the IntelliJ restart or IntelliJ "X" terminate button (instead of JabRef) during development as it can lead to postgres processes hogging memory. I'll add it.
Status update: I did some local prototyping on this but am not pursuing it further — this is available for anyone interested.
Context: The long-term fix may come from #12708 (GSoC project exploring replacing embedded Postgres with an in-process solution), which would eliminate orphan processes by design. However, this issue is worth fixing independently since the solution is straightforward and the problem affects users daily (see @subhramit's report above).
The core challenge: SIGKILL cannot be caught by the JVM — shutdown hooks and AutoCloseable.close() never execute. Approaches explored in this thread:
Approach
Handles SIGKILL?
Trade-off
Pipe-EOF monitor — spawn a lightweight watchdog process connected to JabRef via stdin; kernel closes pipe on parent death → watchdog kills Postgres
Yes, immediately
Adds an extra OS process
PID file + next-launch cleanup — write Postgres PID to disk, check/kill on next JabRef start
No (delayed until next launch)
Simple, no extra process, but stale instances linger
JVM shutdown hook
No (SIGTERM/System.exit only)
Already provided by zonkyio; doesn't help with SIGKILL
The pipe-EOF approach is the most robust — see @Siedlerchr's linked resources on signal handling and @subhramit's findings confirming shutdown hooks don't fire on SIGKILL.
For anyone picking this up: The PID-file approach (suggested by @UdayHE) is the simplest starting point. The pipe-EOF monitor is more robust if you want immediate cleanup. Either would be a welcome improvement.
Pipe-EOF monitor — spawn a lightweight watchdog process connected to JabRef via stdin; kernel closes pipe on parent death → watchdog kills Postgres
For whatever reason, this did not work on Windows.
I also want to highlight that unless we someday decide to allow only one running JabRef instance, there may be cases of multiplicity between JabRef and Postgres processes that may need handling.
Activity
Siedlerchr commentedon Mar 28, 2025
Sigkill cannot be caught, but it would probably make sense to add a shutdown hook to ensure running instances are closed when sigterm occurs
subhramit commentedon Mar 28, 2025
I have faced this too (noticed this yesterday). Every time I close and re-run JabRef (when running via IntelliJ), my task manager shows the old Postgres instance running. On running a new JabRef session again, a new Postgres session is also launched. After 5-6 trials, I was wondering why my system was lagging so much, then checked the task manager which had 6 running postgres instances.
Edit - what I meant was another implication of this is lag during development.
Edit - more details:
1st run: 1 background process, 6 instances:
Second run using IntelliJ reload:
Now there are 2 background processes, 12 instances:
All of them on CPU 00:
And so on...
Siedlerchr commentedon Mar 28, 2025
https://adambien.blog/roller/abien/entry/sigterm_sigint_sigkill_and_java
something like this would probably help
https://docs.oracle.com/en/java/javase/21/troubleshoot/handle-signals-and-exceptions.html
subhramit commentedon Mar 28, 2025
Tried with:
Didn't work
subhramit commentedon Mar 28, 2025
On checking logs, neither the try nor the catch is executed. On reading more, it appears that it's because there is no way to reliably execute code in case of a SIGKILL (the shutdownhook helps in case of SIGTERM and SIGINT).
Siedlerchr commentedon Mar 28, 2025
subhramit commentedon Mar 28, 2025
Hmm...so is this issue unsolvable from the perspective of shutdown it seems..
koppor commentedon Mar 29, 2025
Idea for workaround: On start of new JabRef instance, old postgres (from JabRef) could be re-used (or killed)
ungerts commentedon Mar 29, 2025
To me, this feels a bit like performing "magic" on the user's machine. Implementing such behavior is likely to be complex and error-prone.
PostgreSQL ports are allocated automatically. As a result, the application would need to either:
Multiple PostgreSQL instances might be running on the user's system:
This leads to a critical question: Which instance should JabRef attempt to reuse - or safely shut down?
38 remaining items
subhramit commentedon Jan 5, 2026
I am thinking whether handling SIGKILL is something a software should (or can) make behavioral guarantees about, since control can no longer be in hands of it.
For crashes - i think we should look at the reason. Only if caused due to something going wrong in jabref, we should fix that.
For forceful termination - again, that is not an intended way to use JabRef.
If there was a way to handle sigkill gracefully, we would. But until then, and in one perspective, this issue seems to be intended behavior.
Reusing postgres instances should be a separate issue, and this IMO could be closed.
@koppor we need to add to devdocs not to use the IntelliJ restart or IntelliJ "X" terminate button (instead of JabRef) during development as it can lead to postgres processes hogging memory. I'll add it.
k3KAW8Pnf7mkmdSMPHz27 commentedon Mar 2, 2026
Status update: I did some local prototyping on this but am not pursuing it further — this is available for anyone interested.
Context: The long-term fix may come from #12708 (GSoC project exploring replacing embedded Postgres with an in-process solution), which would eliminate orphan processes by design. However, this issue is worth fixing independently since the solution is straightforward and the problem affects users daily (see @subhramit's report above).
The core challenge: SIGKILL cannot be caught by the JVM — shutdown hooks and
AutoCloseable.close()never execute. Approaches explored in this thread:The pipe-EOF approach is the most robust — see @Siedlerchr's linked resources on signal handling and @subhramit's findings confirming shutdown hooks don't fire on SIGKILL.
For anyone picking this up: The PID-file approach (suggested by @UdayHE) is the simplest starting point. The pipe-EOF monitor is more robust if you want immediate cleanup. Either would be a welcome improvement.
subhramit commentedon Mar 2, 2026
For whatever reason, this did not work on Windows.
I also want to highlight that unless we someday decide to allow only one running JabRef instance, there may be cases of multiplicity between JabRef and Postgres processes that may need handling.
subhramit commentedon Jun 23, 2026
We received a proposal this year, summarized (via AI) below, that would mostly fix this:
Proposed Action Plan
Implement a Data Access Layer (DAL)
BibDatabaseusage.Integrate Lucene search
Refactor the GUI to use the DAL
MainTableand related components to retrieve data through the DAL.Maintain compatibility with existing workflows
.bib-based workflows continue to function.Test and optimize
Expected Outcome
Replace JabRef's current in-memory architecture with a hybrid SQLite (storage) + Lucene (search) backend that:
Refs. #12708 (comment)
koppor commentedon Jun 23, 2026
ADR and MWEs for the backends are done at JabRef#727
MWEs really with a Docker image spawning Java programs and checking things. I thought, JBang would be a nice tool there ^^