-
Notifications
You must be signed in to change notification settings - Fork 371
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
Use api that "stack trace unavailable" in sub-thread #130
Comments
Wow, I can reproduce that, and that is very very wrong. The "stack trace unavailable" seems less wrong than the fact that the histogram thought the smallest bucket should be 225 petabytes and the largest one should be 434 million vigintillion yottabytes - even though all of those buckets except one is empty. How very strange... |
Well, I've figured out what's happening for each of those bugs. The histogram one is easy: we go off the rails when all of the allocation locations have allocated the same amount of memory (we're careful to avoid a divide by zero, but what we do instead isn't terribly helpful). The other problem, the one that you raised the issue for, is trickier. What's happening is that, when the tracker is started in one thread, we're failing to install our profile function on the other threads, which means that we're failing to collect the Python stack of the main thread leading up to the allocations. I'm not sure what to do about that just yet. |
This is expected: thread profile functions only affect newly created threads and the Also, even if we install a profile function, the main thread will continue to be untracked because it never entered new functions while we are tracking in another thread, so we won't see a frame push or a pop. For the main thread we can call I think we should:
|
How about if we make PyInterpreterState* interp = PyThreadState_GetInterpreter(PyThreadState_Get());
PyThreadState* ts = PyInterpreterState_ThreadHead(interp);
while (ts) {
if (_PyEval_SetProfile(ts, PyTraceFunction, PyLong_FromLong(123)) < 0) {
PyErr_Clear();
}
ts = PyThreadState_Next(ts);
} Everything that uses is public except for
When we install the profile function on a thread, perhaps we could also capture its initial stack, since at the point where we would be installing the profile function, we're holding the GIL and could walk the stack backwards from the thread's current frame. We could then apply any later pushes/pops on top of our captured initial stack. |
This means it is not supported and there is no assurance we can do this in the future, that's why I said "supported way" 😉 OTOH we can go with this for now meanwhile I raise this issue with the rest of the core team and we can consider making |
Sure, fair enough. It is available in 3.7 through 3.11, though, at least. And I can't see much reason why it shouldn't be public - it's just
I think that's a good idea. If there's not resistance to that, then that seems like a reasonable way for us to proceed. If there is resistance to it, then we could always interpose the pthreads functions used to acquire the GIL, giving us a hook into when the GIL is next picked up in whatever other thread is already running 😈 |
Another option would be for us to use the public and documented |
I'm not gonna pretend to have a good handle on the thread state APIs, but - could we iterate through the interpreter's thread states and, for each of them, use If that's valid, it would only use public APIs, but there's an assertion I don't understand in |
(I'm guessing that the answer is "no", and that it's not valid to use a thread state on a different OS thread than the one that it was created for, but that doesn't seem to be documented anywhere...) |
I'm not at my computer so I cannot check but if I recall correctly The other method we discussed is much more attainable than messing directly with the thread APIs. |
Right, any usage of It's only using |
I had a situation that main thread has a function and its memory grows up slowly, at the same time I open a sub-thread to monitor this
in the end, "stack trace unavailable" is printed on the screen , I can't get the detail which line consume memory
The text was updated successfully, but these errors were encountered: