Open mbelikov opened 7 years ago
Deadlock occurs, because screen has synchronized methods that call synchronized methods of Terminal, and by means of your resize listener, synchronized methods of the Terminal may now also call synchronized methods of the Screen ==> potential deadlock.
You shouldn't ever need to call screen.doResizeIfNecessary() from the Terminal's resize listener, because main thread already calls it in each iteration of the main loop.
Hi avl42,
sorry, didn't get your point about 'main thread already calls it in each iteration of the main loop'. Which loop in the main thread do you mean? The problem is that in my code we have differnt threads with different synchronization nesting order as far as I understand you. The proper order is then to allow calls from Screen-level to Terminal-level only and not vice-versa, right?
Ok, it is probably not a proper way to get laterna framework handling the resizes well but at least a convinient one: the screen is a super-level of the terminal but without calling of the screen.doResizeIfNecessary()
the SwingTerminal under Windows doesn't repair the content after resizing (shrinking + expanding) so I just get to see the content of the last smallest terminal size. And this resize listener at the Terminal is the only place I've found where it can be catched...
How I can get then my app working properly on Windows?
Regards, mb
You're right about asking back, and I apologize for my too cursory diagnose. (I was thinking of method "addWindowAndWait(Window)" of class MultiWindowTextGUI, but you're not using the textGui layer as far as what can be seen from the cited parts.)
Instead, the main thread is still in progress of trying to set up the Terminal from within startScreen(), when the Terminal first calls the resize listener. Have you read about the "dining philosophers" problem? If not, then google it. That's what happens here: One "dining philosopher" has the terminal lock and wants to also get the screen lock, the other one already has the screen lock and needs the terminal lock -> starvation!
The only appropriate thing to do from the resize listener is calling screen's addResizeRequest(...), and whatever thread ever calls startScreen() is also reponsible to poll doResizeIfNecessary() every once in a while.
It's just so, and you see what you get from ignoring it. And there's really nothing Lanterna could do to help you in this case.
What is your main thread doing in the "// ..." part? playing an animation? waiting for user input? then there's likely already some loop in your code. -- Nothing visible at all? Then why care about resizing the screen at all?
by the way, if the only thing ever written to screen is the String "Hello from lanterna!" then once you let the screen shrink with the Terminal to a smaller size and grow it again, then the screen itself will have forgotten your string.
S. the issue #2 The last version of the lanterna seems still to have race condition / deadlock issue at least on Windows. The deadlock is easily to reproduce, just imagine the following code (I've used scala):
If I run it on my machine (i7 CPU with 4 cores) in more as 50% of runs I do get a deadlock.
The deadlock:
Platform used:
Adding some
seems to fix the problem (e.g. after
terminal = factory.createTerminalEmulator()
andval screen: Screen = new VirtualScreen(new TerminalScreen(terminal))
) => race condition