Should I call flush_signals before schedule or schedule_timeout ??? - Linux

This is a discussion on Should I call flush_signals before schedule or schedule_timeout ??? - Linux ; Hi, Question: how should I clear the pre-existing signals before starting wait on the queue? Or how can I wait only on my own signals and ignore everything else? Details: When my driver gets close file request, it cannot return ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: Should I call flush_signals before schedule or schedule_timeout ???

  1. Should I call flush_signals before schedule or schedule_timeout ???

    Hi,

    Question: how should I clear the pre-existing signals before starting wait
    on the queue?
    Or how can I wait only on my own signals and ignore everything else?

    Details:
    When my driver gets close file request, it cannot return immediately, but
    have to wait for completion of some async operations. So, I studied some
    tutorials, such as http://www.linuxjournal.com/article/8144 and
    http://lwn.net/Articles/22913/ and finally wrote the waiting loop (actually
    I borrowed it from usb.c in my 2.4 kernel):

    DECLARE_WAITQUEUE(wait, current);
    DECLARE_WAIT_QUEUE_HEAD(wqh);

    init_waitqueue_head(&wqh);
    current->state = TASK_INTERRUPTIBLE;
    add_wait_queue(&wqh, &wait);

    while (timeout && (my_condition))
    {
    timeout = schedule_timeout(timeout);
    current->state = TASK_INTERRUPTIBLE;
    }
    current->state = TASK_RUNNING;
    remove_wait_queue(&wqh, &wait);

    When the application closes the file normally, the schedule_timeout starts
    waiting.
    Then my bottom half calls wake_up on &wqh and the loop terminates.

    But when the application is terminated by Ctrl+C, the signal is set in the
    current task and schedule_timeout returns immediately, which results in a
    tight polling loop, which I want to avoid.

    I found that if a clear the signal using flush_signals(current) before the
    first line in the code above, then, of course, loop waits as it supposed to.
    But I am afraid to screw something else by clearing all signals.

    This scenario (terminating apps by Ctrl+C) is so common, that I am sure that
    this issue came up many times already, but I cannot find any good example or
    explanation how to solve it.

    Thank you
    John







  2. Re: Should I call flush_signals before schedule or schedule_timeout ???

    John wrote:
    > Hi,
    >
    > Question: how should I clear the pre-existing signals before starting wait
    > on the queue?


    You shouldn't. That's not your business. If something raised signals
    against the task, they should be processed normally, and not thrown
    away.

    > Or how can I wait only on my own signals and ignore everything else?


    One way is to manipulate the process signal mask. Signals can be
    blocked. Not all of them, though: for instance, not SIGKILL.

    > Details:
    > When my driver gets close file request, it cannot return immediately, but
    > have to wait for completion of some async operations.


    If it's truly critical to complete those operations before completing
    the close, and there is a near guarantee (an assurance that, short of
    defects in the hardware or software) that those async operations will
    complete, and in a reasonable time, then use an uninterruptible sleep.

    Nothing will wake the task from an uninterruptible sleep, not even a
    SIGKILL termination attempt.

    > But when the application is terminated by Ctrl+C, the signal is set in the
    > current task and schedule_timeout returns immediately, which results in a
    > tight polling loop, which I want to avoid.


    You could implement a background close. Detach your device from the
    file descriptor and allow that descriptor to be closed without delay.
    You can handle closing independently of the original requesting process
    and its file descriptor. The TCP stack does this with closed
    connections, for instance. The process which had that device open
    should even be able to terminate entirely. That has nothing to do with
    your device any longer once the descriptor is detached.

    A special ioctl() operation could be provided for applications that
    want to wait for all async operations to complete. That ioctl() will
    nicely return an EINTR result if it is interrupted by a signal, to
    indicate that the waited-for event might not have happened.


  3. Re: Should I call flush_signals before schedule or schedule_timeout ???

    Thank you for your response.

    I would like to clarify some points:

    >> When my driver gets close file request, it cannot return immediately, but
    >> have to wait for completion of some async operations.

    >
    > If it's truly critical to complete those operations before completing
    > the close, and there is a near guarantee (an assurance that, short of
    > defects in the hardware or software) that those async operations will
    > complete, and in a reasonable time, then use an uninterruptible sleep.


    No, I don't want to use uninterruptible sleep because I only want to sleep
    until my bottom half is invoked and wakes up the waiting process.
    Usually this signal happens very quickly and I don't want to wait for any
    fixed
    timeout becase that would be a waste of time.
    And my scheme works just fine in all cases except when Ctrl+C causes
    early wake ups.

    > You could implement a background close. Detach your device from the
    > file descriptor and allow that descriptor to be closed without delay.


    I don't think I can do this easily. I am writing a USB serial driver, which
    works in tight cooperation with usbserial.c, which passes "port" pointer
    to many routines (including bottom halves). If I return from "close" routine
    before all async opertions are completed, then bottom halves operate
    on invalid "port" and the system crashes.

    May be I can rewrite the whole thing and stop passing "port" around, but
    this is too big change and I don't need it because my current scheme
    (waiting inside "close" routine) works just fine except for Ctrl+C issue.

    So, if I would find a way to wait on my own private signal and not to be
    disturbed by all other signals, this will be great.

    Thank you
    John





  4. Re: Should I call flush_signals before schedule or schedule_timeout ???


    John wrote:
    > Thank you for your response.
    >
    > I would like to clarify some points:
    >
    > >> When my driver gets close file request, it cannot return immediately, but
    > >> have to wait for completion of some async operations.

    > >
    > > If it's truly critical to complete those operations before completing
    > > the close, and there is a near guarantee (an assurance that, short of
    > > defects in the hardware or software) that those async operations will
    > > complete, and in a reasonable time, then use an uninterruptible sleep.

    >
    > No, I don't want to use uninterruptible sleep because I only want to sleep
    > until my bottom half is invoked and wakes up the waiting process.
    > Usually this signal happens very quickly and I don't want to wait for any
    > fixed
    > timeout becase that would be a waste of time.


    Uninterruptible sleep is probably the perfect tool then.
    Uninterruptible sleep doesn't mean "fixed timeout". It means
    "scheduling delay that cannot be interrupted by a signal". Of course,
    an uninterruptible sleep can still be woken by an explicit wakeup().

    > And my scheme works just fine in all cases except when Ctrl+C causes
    > early wake ups.


    Ctrl-C would have no effect on uninterruptible sleep, without having to
    do anything with the pending signals or their mask.

    > > You could implement a background close. Detach your device from the
    > > file descriptor and allow that descriptor to be closed without delay.

    >
    > I don't think I can do this easily. I am writing a USB serial driver, which
    > works in tight cooperation with usbserial.c, which passes "port" pointer
    > to many routines (including bottom halves). If I return from "close" routine
    > before all async opertions are completed, then bottom halves operate
    > on invalid "port" and the system crashes.


    Not if there is some intermediate context object which has a life of
    its own, independent of the file descriptor, and that object holds on
    to the port.

    How did you associate your driver data with the file descriptor?

    Chances are you have some pointer to a dynamically allocated structure
    which you set up when the descriptor is open, associate it with the
    descriptor, and then tear it down when the descriptor is closed.

    Suppose it was a reference-counted object. The descriptor could hold a
    reference, and so could any pending async operations. Closing the
    descriptor would mean breaking the association to the object and
    releasing the reference. Then when the async operations all come in and
    drop their references, the object is blown away.


  5. Re: Should I call flush_signals before schedule or schedule_timeout ???

    > Uninterruptible sleep is probably the perfect tool then.
    > Uninterruptible sleep doesn't mean "fixed timeout". It means
    > "scheduling delay that cannot be interrupted by a signal". Of course,
    > an uninterruptible sleep can still be woken by an explicit wakeup().


    Yes, thank you. I missed this point before. I tried replacing
    TASK_UNINTERRUPTIBLE by TASK_INTERRUPTIBLE this morning
    (after your first response) and was having timeouts, but now I tested
    again and see that it works OK. I will, probably, use this approach.

    Originaly I copied my code from usb_start_wait_urb in usb.c,
    which used TASK_INTERRUPTIBLE:

    current->state = TASK_INTERRUPTIBLE;
    .....
    while (timeout && urb->status == -EINPROGRESS)
    status = timeout = schedule_timeout(timeout);

    which, in my opinion, is really stupid because this loop
    is not really interrupted but degenerates to tight polling (am I right?)

    Now I searched other linux sources (also 2.4.x)
    and see that the same function is done differently:

    set_current_state(TASK_UNINTERRUPTIBLE);
    ....
    while (timeout && !awd.done)
    {
    timeout = schedule_timeout(timeout);
    set_current_state(TASK_UNINTERRUPTIBLE);
    rmb();
    }

    So, I will, probably, do TASK_UNINTERRUPTIBLE
    like in the second example since my timeout is really short
    and I will not inconvenience anybody by blocking even in the worst case.


    > How did you associate your driver data with the file descriptor?
    >
    > Chances are you have some pointer to a dynamically allocated structure
    > which you set up when the descriptor is open, associate it with the
    > descriptor, and then tear it down when the descriptor is closed.
    >
    > Suppose it was a reference-counted object. The descriptor could hold a
    > reference, and so could any pending async operations. Closing the
    > descriptor would mean breaking the association to the object and
    > releasing the reference. Then when the async operations all come in and
    > drop their references, the object is blown away.
    >


    Yes, you are right, I can, probably, hold on to the "port" object longer and
    move wait to "open" function (since I don't want somebody to re-open
    the port while I am closing it).

    Thank you
    John




+ Reply to Thread