Mike wrote:
... I'm not sure how this works. You create a new "raw" kernel thread using clone, then run NT code using it. But that isn't valid and may not work - only threads created by Wine may use Win32.
The right thing to do would be to promote the linux thread to be a win32 thread, but as a temporary stopgap, Thomas had the linux thread just do CreateThread and exit, hoping that the newly create Windows thread was healthy. Maybe we should look more carefully about what it takes to build a normal, healthy win32 thread from a posix thread.
You are using ptrace instead of signals. That seems over complex - signals are designed to interrupt a thread ...
Well, kind of. Signals are only delivered when syscalls return, so they won't work well if the thread you pick to molest happens to not make any syscalls for a long time. (Plus, signals aren't completely reliable... see http://www.opengroup.org/austin/mailarchives/ag/msg07173.html for a 2004 proposal for making signals reliable.)
You don't preserve the register state.
Really? What's ptrace(PTRACE_GETREGS, pid, NULL, regs) then, chopped liver? :-)
[Why not queue a windows APC?]
Well, if Alexandre thinks that's the way to go, that'd be fine. I thought those only fired when the thread in question performed an alertable wait condition (so says http://msdn.microsoft.com/library/en-us/dllproc/base/queueuserapc.asp ) so it didn't seem like an obvious way to go. - Dan
"Dan Kegel" dank@kegel.com writes:
Well, kind of. Signals are only delivered when syscalls return, so they won't work well if the thread you pick to molest happens to not make any syscalls for a long time.
Signals certainly don't need system calls to be delivered. IMO they would be more appropriate than ptrace in this case. At least signals can be masked during server calls, though of course it doesn't solve the issue of interrupting a thread holding a lock. Cloning a new thread is not going to help with this at all, since it still uses the Win32 context of the original thread, so it only makes things worse.
On 7/16/06, Alexandre Julliard julliard@winehq.org wrote:
Cloning a new thread is not going to help with this at all, since it still uses the Win32 context of the original thread, so it only makes things worse.
What then is the solution? A service thread? I think it'd be OK to have the hijacked thread be holding a lock, as CreateThread doesn't seem to wait on the newly created thread anywhere.
thanks -mike
On 7/16/06, Alexandre Julliard julliard@winehq.org wrote:
Well, kind of. Signals are only delivered when syscalls return, so they won't work well if the thread you pick to molest happens to not make any syscalls for a long time.
Signals certainly don't need system calls to be delivered.
I stand corrected. Signals get delivered on return from a system call *or* on return from an interrupt. (But on systems configured with CONFIG_NO_HZ, it could be a while before there's an interrupt, couldn't it?)
IMO they would be more appropriate than ptrace in this case. At least signals can be masked during server calls, though of course it doesn't solve the issue of interrupting a thread holding a lock. Cloning a new thread is not going to help with this at all, since it still uses the Win32 context of the original thread, so it only makes things worse.
I'm afraid I don't quite understand. What's wrong with interrupting a thread holding a lock? Could that make cloning a new thread deadlock? - Dan
On 7/16/06, Dan Kegel dank@kegel.com wrote:
On 7/16/06, Alexandre Julliard julliard@winehq.org wrote:
Well, kind of. Signals are only delivered when syscalls return, so they won't work well if the thread you pick to molest happens to not make any syscalls for a long time.
Signals certainly don't need system calls to be delivered.
I stand corrected. Signals get delivered on return from a system call *or* on return from an interrupt. (But on systems configured with CONFIG_NO_HZ, it could be a while before there's an interrupt, couldn't it?)
I guess the worst case is the signal will be delivered at the beginning of the next time slice, so that shouldn't be too long. - Dan
"Dan Kegel" dank@kegel.com writes:
I guess the worst case is the signal will be delivered at the beginning of the next time slice, so that shouldn't be too long.
There's no need to wait for that. On a UP system obviously the thread is interrupted already since you are doing a kill syscall. On SMP an inter-CPU interrupt is sent.
"Dan Kegel" dank@kegel.com writes:
I'm afraid I don't quite understand. What's wrong with interrupting a thread holding a lock? Could that make cloning a new thread deadlock?
One problem is that many locks have to be acquired in a specific order to avoid deadlocks, and since you don't know which locks the thread is already holding you can't guarantee the order. The other problem is that you can't guarantee that critical sections are in a valid state since the thread could be interrupted in the middle of a crit section call.
Hi,
On Mon, Jul 17, 2006 at 01:08:38PM +0200, Alexandre Julliard wrote:
"Dan Kegel" dank@kegel.com writes:
I'm afraid I don't quite understand. What's wrong with interrupting a thread holding a lock? Could that make cloning a new thread deadlock?
One problem is that many locks have to be acquired in a specific order to avoid deadlocks, and since you don't know which locks the thread is already holding you can't guarantee the order. The other problem is that you can't guarantee that critical sections are in a valid state since the thread could be interrupted in the middle of a crit section call.
The second problem could possibly be workarounded by some very gross hacks:
Add hooks in a number of *very* common Win32 API functions (GetVersion(), PeekMessage(), ...) that would "trap" this thread there (add huge Sleeps etc.) while it's being grossly abused externally:
if (unlikely(ongoing_create_remote_operation)) freeze_thread();
That way you'd make certain that any object the thread is modifying during its life-time is not suspended in half-modified state during the time that you're doing brain surgery on this thread.
Not a pretty solution at all, but it could help - unless I'm totally mistaken due to uninformedly jumping into the middle of this discussion.
Andreas Mohr
On 7/17/06, Alexandre Julliard julliard@winehq.org wrote:
"Dan Kegel" dank@kegel.com writes:
I'm afraid I don't quite understand. What's wrong with interrupting a thread holding a lock? Could that make cloning a new thread deadlock?
One problem is that many locks have to be acquired in a specific order to avoid deadlocks, and since you don't know which locks the thread is already holding you can't guarantee the order. The other problem is that you can't guarantee that critical sections are in a valid state since the thread could be interrupted in the middle of a crit section call.
I was thinking that cloning the process could take care of deadlocks. What if the cloned thread fudges its teb and sets a different thread id than its cloning thread? This invalidates all locks in the cloned thread taken by the cloning thread. Both threads continue and any contention would be handled in the already thread-safe manner.
Thomas Kho
"Thomas Kho" tkho@ucla.edu writes:
I was thinking that cloning the process could take care of deadlocks. What if the cloned thread fudges its teb and sets a different thread id than its cloning thread? This invalidates all locks in the cloned thread taken by the cloning thread. Both threads continue and any contention would be handled in the already thread-safe manner.
Simply cloning the thread is not going to solve anything. You need to build a proper Win32 context for that thread; but then of course your problem is solved, and you don't need to make it create another thread...