Signal processor for accessing the queue data structure (race condition?)

I am currently writing a small shell in C ++.

Jobs and their associated PIDs are stored in the (job *) pointer queue (job *) . When a new task starts, information about this is added to the queue. Since several tasks can be processed simultaneously, and new tasks can be entered into the console console at any time, I have a signal handler to wait for the tasks to complete.

When the task is completed, I need to remove it from the active task queue and transfer it to my deque of completed tasks. However, it is possible that a new user job is added to the queue when another job is stopped.

In this case, their insert operation will be suspended, and my signal handler will be called, which will perform the pop operation.

I am trying to understand how I can resolve this potential race condition, since I assume that corruption can occur during this process. I cannot use the mutex, because a deadlock will occur if the intermittent parent process uses the queue at that time.

I see some information on C++11 that is capable of atomic operations declared by the user, as well as information about tasks. I am not sure that they relate to my question.

Interestingly, the shell example (MSH - http://code.google.com/p/mini-shell-msh/ ) that I use as a link does not seem to handle such conditions. The signal handler immediately modifies the job list along with the main console. Maybe I don’t notice something here?

As always, all feedback is assigned.

+6
source share
2 answers

You have several ways to avoid a race condition.

  • Use the pending (atomic) queue for job pointers;
  • use any other queue, but protect it with sigprocmask (in non-handler code) and with the correct sigaction value in the sigaction call;
  • do not use a signal handler at all, use an intolerable system call that allows you to work with signals synchronously: in Linux this is possible with signalfd , which is not sure about other platforms.
+4
source

You need to disable signals with sigprocmask() around the critical sections of the non-handler code. This is similar to device drivers in disabling kernel interrupts in half of the user driver when updating structures shared by the interrupt handler.

+1
source

Source: https://habr.com/ru/post/901583/


All Articles