> I am using utrace for a school project.

Great!  Thanks for your interest in utrace.

> I would like to trace system calls for an application an all its
> descendants, and transmit them to user space.  I have implemented a
> circular buffer, in which i can place a simple message, and then export
> the buffer to user space with a character device.

Feel free to share your code here even if it's not at all ready for prime
time.

> (i did it with set_current_status(TASK_INTERRUPTIBLE) and sleep() then
> wake_up_task from the producers).

That's the fundamental way to do it, and the correct style of thing from
the utrace perspective.  You might want to use some slightly higher-level
facilities available in the kernel (that translate into that same sort of
thing at low level), such as wait_event_interruptible() (linux/wait.h),
wait_for_completion_interruptible (linux/completion.h), etc.

> I tried to synchronized the consumers with UTRACE_STOP and
> utrace_control(UTRACE_RESUME) and it works fine. 

Excellent!

> The problem is that (if i understood correctly) when returning from
> UTRACE_STOP from a monitor function like SYSCALL_ENTRY, my callback won'
> be called again for the same system call on UTRACE_RESUME. This way if
> the buffer is full and i return UTRACE_STOP, i will loose the possibility
> to log the syscall_entry into the buffer.

This exact problem is addressed in recent versions of utrace (with
UTRACE_API_VERSION >= 20090421).  If you use UTRACE_REPORT rather than
UTRACE_RESUME, then report_syscall_entry will be called a second time.
This time its @action will have the UTRACE_SYSCALL_RESUMED bit set.  That
flag tells you that this is a second (or later) repeated report for the
same syscall entry after your engine or another one has used UTRACE_STOP
and then resumed.  

There is another wrinkle about this that you will encounter when working
with another engine that might modify syscall parameters (e.g. kmview or
ptrace).  The recommended protocol is to do:

        if (utrace_resume_action(action) == UTRACE_STOP)
                return UTRACE_SYSCALL_RUN | UTRACE_REPORT;

first thing, even if you don't need to stop for your own work.  That
handles the case where another engine has stopped the thread so as to
fiddle with its registers.  You won't do your notification/logging yet,
but instead get the next callback with (action & UTRACE_SYSCALL_RESUMED)
when you can see the registers as modified by the other engine.  Note
that one or more other engines might stop and resume multiple times
before actually letting the syscall proceed.  So you should check the
incoming utrace_resume_action as above even for a call that comes in
with UTRACE_SYSCALL_RESUMED set.

> Calling schedule() from the utrace callback while the buffer is full
> would solve the problem, but as i understand that is not recommended,
> since it doesn't play nice with other monitoring engines that might be
> active.

Correct.  Don't do that!

> How could i solve this problem and still be friendly with utrace?

I think UTRACE_REPORT->UTRACE_SYSCALL_RESUMED takes care of your issue.


Thanks,
Roland

Reply via email to