Closed lps-rocks closed 4 years ago
It looks like because the resizing work is done inside the resize signal handler this is triggering the bug. Python project suggests deferring any changes to outside the signal handler.
Thanks for reporting. Just a couple questions. Are you using Enlighten within multiple threads? Do you have sample code that demonstrates the behavior?
@avylove - I am using it with multiple threads, the manager and all of the status bars are called and updated from the main thread, however there are some other threads that are using logging and could be writing to the enlighten logger.
I did also just realize I'm not on the latest version and it does look like there were some changes to the resizing functions between 1.6.0 and 1.6.1 - That could be playing a part. I'm going to test 1.6.1 as soon as I get my internal python mirror sync'd (for some reason it stopped syncing).
Enlighten doesn't have a logger. It's looks like the resize handler is trying to use stdout when another thread has it.
I'm not sure the latest version will make a difference if I'm understanding the issue. Essentially the resize_handler will have to only flag that a resize needs to occur and the resize would have to be delayed until the next time a write is made by the manager. That seems doable, but I'm not sure when I can get to it.
In the meantime, if you want to disable resize, you can pass no_resize
to the manager.
I'll try to make the changes, but if you can send me some minimal code to demonstrate it would go a long way.
I'll see if I can get some code that easily reproduces it that isn't protected by copyright. Thanks much for checking this out.
So I did try latest version, it also did not solve the issue, what I did find is that if i wrote to stdout from any other thread while resizing it would trigger this bug. If I wrote to the logger from only the main thread where enlighten was being called from, this wouldn't happen.
I was able to reproduce the issue with the following code. Now that I have a way to test, I'll try to work on a fix.
import os
import random
import signal
import sys
import threading
import time
import enlighten
RUN = True
TOTAL = 100
PID = os.getpid()
def print_hello():
while RUN:
print('hello')
def resize_constantly():
while RUN:
os.kill(PID, signal.SIGWINCH)
manager = enlighten.get_manager()
ticks = manager.counter(total=TOTAL, desc='Ticks', unit='ticks')
assert manager.process_exit
t1 = threading.Thread(target=print_hello)
t2 = threading.Thread(target=resize_constantly)
t1.start()
t2.start()
try:
for num in range(TOTAL):
time.sleep(random.uniform(0.05, 0.1))
print(num)
ticks.update()
except:
RUN = False
raise
manager.stop()
RUN = False
@lps-rocks I put a fix in 021a2561d629db014952713f8697678c10a043f7. Please try it out and confirm it resolves your issue.
I may have back this out in the next release because it has unintended consequences. Specifically, the output gets corrupted if something is written to the screen between the resize event and the next call of manager.write(). This can be fixed by wrapping stdout so it handles resizing events on the next write, but that could get complicated.
Didn't back out, but 1.7.0 introduces a new parameter for Manager()
, threaded
. If threaded
is True
, resizing will be deferred, otherwise it will be handled by the signal handler. threaded
defaults to True
if multiple signals are detected, threading.active_count() > 1
, so it should be automatic if the manager is initialized after threads are created, but I suggest using enlighten.get_manager(threaded=True)
to be sure.
Describe the bug When resizing the window the thread running enlighten crashes
To Reproduce Resize window while running with multiple threads
Environment (please complete the following information):
Additional context