-
Notifications
You must be signed in to change notification settings - Fork 7.4k
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
ctrl-c after idf.py gdb isn't properly caught and is behaving as if its in the background in the terminal (IDFGH-10638) #11871
Comments
Here is the text from the terminal where you can see something is odd. I hit ctrl-c after a moment of the line '(gdb)' after the '79' showed up. ctrl-c resulted in 'Quit' and dropped me back to a shell where I hit enter and "A debugging session is active" and the following text appeared.
|
idf_py_gdb.webmHere is a screen recording of the issue. |
Hello @cmorganBE ,
changed the behavior of the |
Looking into this more closely I think this is problem in cpython. The if lock.locked(): doesn't seem right, because there is IMHO no way how to find out if the lock was actually acquired and is not held by something else(e.g. still held from the thread bootstrap code. #!/usr/bin/env python3
import threading
import time
def fun(count):
while count:
print('sleeping ...')
time.sleep(1)
count -= 1
print('thread exited')
t = threading.Thread(target=fun, args=(30,))
t.start()
while True:
try:
print('join started')
t.join()
print('thread joined')
break
except KeyboardInterrupt:
print('SIGINT')
continue
|
There is already a bug reported about this in cpython python/cpython#90882. I guess we will have to workaround this somehow. |
@fhrbata thank you for looking into this in such depth and for fixing it, I had reasonably low expectations, its one issue reported among hundreds or thousands, but I'm appreciative that this was resolved in what looks like a clean and correct manner |
@cmorganBE Thank you and hopefully the fix is working for you. I would like to thank you one more time for such detailed bug report. It's very much appreciated! |
idf.py spawns gdb process within a thread and uses Thread.join() to wait for the gdb process to finish. As CTRL+C(SIGINT) is used by gdb to interrupt the running program, we catch the SIGINT while waiting on the gdb to finish, and try Thread.join() again. With cpython's commit commit a22be4943c119fecf5433d999227ff78fc2e5741 Author: Victor Stinner <[email protected]> Date: Mon Sep 27 14:20:31 2021 +0200 bpo-45274: Fix Thread._wait_for_tstate_lock() race condition (GH-28532) this logic doesn't work anymore, because cpython internally marks the thread as stopped when join() is interrupted with an exception. IMHO this is broken in cpython and there is a bug report about this python/cpython#90882. Problem is that waiting on a thread to finish is based on acquiring a lock. Meaning join() is waiting on _tstate_lock. If this wait is interrupted, the above referenced commit adds a logic that checks if the lock is help, meaning the thread is done and marks the thread as stopped. But there is no way to tell if the lock was acquired by us running join() or if it's held by someone else e.g. still by the thread bootstrap code. Meaning the thread is still running. I may be missing something, but I don't see any reason why to spawn gdb process within a thread. This change removes the thread and spawns gdb directly. Instead waiting on a thread, we wait on the process to finish, replacing join() with wait() and avoiding this problem. Closes espressif#11871 Signed-off-by: Frantisek Hrbata <[email protected]>
idf.py spawns gdb process within a thread and uses Thread.join() to wait for the gdb process to finish. As CTRL+C(SIGINT) is used by gdb to interrupt the running program, we catch the SIGINT while waiting on the gdb to finish, and try Thread.join() again. With cpython's commit commit a22be4943c119fecf5433d999227ff78fc2e5741 Author: Victor Stinner <[email protected]> Date: Mon Sep 27 14:20:31 2021 +0200 bpo-45274: Fix Thread._wait_for_tstate_lock() race condition (GH-28532) this logic doesn't work anymore, because cpython internally marks the thread as stopped when join() is interrupted with an exception. IMHO this is broken in cpython and there is a bug report about this python/cpython#90882. Problem is that waiting on a thread to finish is based on acquiring a lock. Meaning join() is waiting on _tstate_lock. If this wait is interrupted, the above referenced commit adds a logic that checks if the lock is help, meaning the thread is done and marks the thread as stopped. But there is no way to tell if the lock was acquired by us running join() or if it's held by someone else e.g. still by the thread bootstrap code. Meaning the thread is still running. I may be missing something, but I don't see any reason why to spawn gdb process within a thread. This change removes the thread and spawns gdb directly. Instead waiting on a thread, we wait on the process to finish, replacing join() with wait() and avoiding this problem. Closes espressif#11871 Signed-off-by: Frantisek Hrbata <[email protected]>
idf.py spawns gdb process within a thread and uses Thread.join() to wait for the gdb process to finish. As CTRL+C(SIGINT) is used by gdb to interrupt the running program, we catch the SIGINT while waiting on the gdb to finish, and try Thread.join() again. With cpython's commit commit a22be4943c119fecf5433d999227ff78fc2e5741 Author: Victor Stinner <[email protected]> Date: Mon Sep 27 14:20:31 2021 +0200 bpo-45274: Fix Thread._wait_for_tstate_lock() race condition (GH-28532) this logic doesn't work anymore, because cpython internally marks the thread as stopped when join() is interrupted with an exception. IMHO this is broken in cpython and there is a bug report about this python/cpython#90882. Problem is that waiting on a thread to finish is based on acquiring a lock. Meaning join() is waiting on _tstate_lock. If this wait is interrupted, the above referenced commit adds a logic that checks if the lock is help, meaning the thread is done and marks the thread as stopped. But there is no way to tell if the lock was acquired by us running join() or if it's held by someone else e.g. still by the thread bootstrap code. Meaning the thread is still running. I may be missing something, but I don't see any reason why to spawn gdb process within a thread. This change removes the thread and spawns gdb directly. Instead waiting on a thread, we wait on the process to finish, replacing join() with wait() and avoiding this problem. Closes #11871 Signed-off-by: Frantisek Hrbata <[email protected]>
idf.py spawns gdb process within a thread and uses Thread.join() to wait for the gdb process to finish. As CTRL+C(SIGINT) is used by gdb to interrupt the running program, we catch the SIGINT while waiting on the gdb to finish, and try Thread.join() again. With cpython's commit commit a22be4943c119fecf5433d999227ff78fc2e5741 Author: Victor Stinner <[email protected]> Date: Mon Sep 27 14:20:31 2021 +0200 bpo-45274: Fix Thread._wait_for_tstate_lock() race condition (GH-28532) this logic doesn't work anymore, because cpython internally marks the thread as stopped when join() is interrupted with an exception. IMHO this is broken in cpython and there is a bug report about this python/cpython#90882. Problem is that waiting on a thread to finish is based on acquiring a lock. Meaning join() is waiting on _tstate_lock. If this wait is interrupted, the above referenced commit adds a logic that checks if the lock is help, meaning the thread is done and marks the thread as stopped. But there is no way to tell if the lock was acquired by us running join() or if it's held by someone else e.g. still by the thread bootstrap code. Meaning the thread is still running. I may be missing something, but I don't see any reason why to spawn gdb process within a thread. This change removes the thread and spawns gdb directly. Instead waiting on a thread, we wait on the process to finish, replacing join() with wait() and avoiding this problem. Closes #11871 Signed-off-by: Frantisek Hrbata <[email protected]>
Answers checklist.
General issue report
Ubuntu Linux 23.04 x86-64, esp-idf 5.1, using blinky example and esp32-s3-devkitc-1.
Plugged into 'usb' micro-usb-b port, able to idf.py flash but when debugging:
Running idf.py openocd in one terminal, then idf.py gdb in another terminal. The idf.py gdb was waiting for something so I hit ctrl-c so gdb would interrupt the running program and drop me back into a gdb prompt but instead I was dropped out to a shell prompt.
Oddly I continue to get gdb output in the same terminal. It's as if gdb is running in the background and never caught the ctrl-c.
The text was updated successfully, but these errors were encountered: