> I don't understand why this is better than just changing ->ops. Except, > yes, I agree with above.
Sure, if you think about the innards they amount to about the same thing. After PTRACE_DETACH, there is one engine attached and it uses the special ops vector. They are really just different ways to convince oneself that there are no problematic races. To change ->ops we have to convince ourselves from scratch (which indeed perhaps is not all that hard). > Adding another engine during detach adds more complexity, UTRACE_ATTACH_CREATE > can fail, we should create the new context for new_engine->data... It can only fail in pathological OOM situations (I think). There it's probably fine for PTRACE_DETACH to do something strange like yield and return -ERESTARTNOINTR. I'm not sure it needs any context structure. It could just store the signal number with engine->data=(void*)(unsigned long)signr (or just still use someplace else like task->exit_code). > But OK. Let's discuss this later. Agreed. > At least we both agree ptrace_attach() > should not try to re-use the old engine, and detach should use a special > ops vector (with old or new engine). This makes me feel a bit better. I think all three are plausible options. We'll just have to see what seems simplest and cleanest to cover all the corners (i.e. attach/detach races and such) affected by this choice. > Can't understand... Just in case, I'll explain which race I meant. > > Suppose the freshly forked child should be ptraced. In that case > ptrace_init_task(child) does ptrace_link() under write_lock(tasklist). Clearly this is not part of any clean implementation in the long run. In any pure utrace-based implementation, or IMHO even any one with only as much kludgery as ptrace semantics really demand (i.e. wait interference), all related bookkeeping would be driven from ptrace's report_clone hook. Thanks, Roland