What is about polling after I/O service is stopped - boost-asio

Recently I'm working with boost asio and there is a statement I believe ambiguous to readers in documentation
The poll() function runs handlers that are ready to run, without blocking, until the io_service has been stopped or there are no more ready handlers.
To verify my comprehension, an experiment is conducted below
boost::asio::io_service io;
boost::system::error_code error;
boost::asio::signal_set signals(io);
signals.add(SIGINT);signals.add(SIGTERM);signals.add(SIGQUIT);
/* asynchronous wait on signal conditions to stop io service */
signals.async_wait([&io](const boost::system::error_code & code, int val){
io.stop();
});
/* the only main thread polls all file descriptors to dispatch ready handlers */
while(!error)
io.poll(error); /* this is where I expect error arise upon io stopped after signal of interrupt from console is conducted to asynchronous wait handler */
But it appears that call to poll always returns success even that io service is stopped. So the program would not exit by having error as condition of the loop. So my question is, am I right and is there other mechanism I missed to exit the loop of calling poll? Many thanks.

Trying to process a stopped io_service's event loop via run(), run_one(), poll(), or poll_one() is not specified as being an error. The io_service::stop() documentation specifies that it affects poll() by causing subsequent calls to poll() to return immediately until reset() is called. Furthermore, a normal exit from io_service::run() is documented as occurring when the io_service has been stopped, accentuating that attempting to process the event loop on a stopped io_service is not an error:
A normal exit from the run() function implies that the io_service object is stopped (the stopped() function returns true).
To exit from the loop, consider changing the predicate so that the loop stops upon error or when the io_service has been stopped:
while (!error && !io.stopped())
io.poll(error);

Related

How can I safely terminate UdpClient.receive() in case of timeout?

I want to implement a timeout in my UDP Multicast receiver using VB.Net. Basically, if I don't receive any packets in 10 seconds I want to stop listening. I can very easily use a Timer with an interval of 10000 to know when I need to time out, but the question is how do I stop the receive function? If I use the Receive() function (the one that blocks), I could simply stop it with a Thread.Abort() call. Everything I have read, however, has said that this is not a safe practice. If I use the asynchronous BeginReceive() function, I don't know how to terminate it before it finishes normally because EndReceive() will throw an exception if it isn't called with an IASyncResult that is returned from BeginReceive().
The answers to this question led me to investigate the CancelAsync() method. But, the answer to this question made me nervous.
If I use the blocking receive, I will not be able to continuously poll the CancellationPending property unless I call Receive() in its own thread from within the DoWork handler. But that would mean it would continue to run after the cancel takes effect right? If I use BeginReceive(), I am worried that CancelAsync() wil get "eaten" by the DoWork handler and I will end up with the same problem.
Plus, this snippet from the BackgroundWorker documentation is less than reassuring...
Be aware that your code in the DoWork event handler may finish its work as a cancellation request is being made, and your polling loop may miss CancellationPending being set to true. In this case, the Cancelled flag of System.ComponentModel.RunWorkerCompletedEventArgs in your RunWorkerCompleted event handler will not be set to true, even though a cancellation request was made.
One alternative I thought of was having the UdpClient that is sending the packets be in charge of timing out, and then have it send some kind of cancellation signal packet to indicate that the receiver(s) should stop listening. The problem with this is that given the nature of UDP, there is no guarantee that said packet will arrive, or be picked up in the correct order.
Is there a way to safely terminate a UDP receive procedure before it finishes?
I have ran into the same issue with UdpClient and I am not sure what the safe solution is/if a "safe" solution exists. However, I came across a function that a user posted for a different question which tracks and terminates a code block that exceeds a certain time span and I just wrap my call to UdpClient.receive() in it. If you would like to give it a try, the function looks like this:
private static bool TrackFunction(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
task.Wait(timeSpan);
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
And you would simply wrap it around your code like such:
bool timeTracker = TrackFunction(TimeSpan.FromSeconds(10), () =>
{
Byte[] received = myUdpClient.Receive(ref myIPEndPoint);
}
Again, there may be a better solution, but this is just what I have used.
I've run in to a similar situation where I open several connections (Udp, Serial, etc.) with remote devices and need to switch among them in a "listener" thread that uses the blocking UdpClient.Receive() call. Calling Thread.Abort() caused crashes, switching the connection instance (the UdpClient) without first exiting the thread didn't work either, because the thread was hung on the UdpClient.Receive() and a simple flag in a while loop never exited.
What did finally work was to close the connection in the main application thread, this would cause UdpClient.Receive() to throw an exception that could be caught and dealt with. The application creates instances of UdpClient that represent the various connections and starts a "listener" thread that can be terminated by setting a global flag and closing the current UdpClient instance. I used VB.NET and it looked something like this:
Dim mListening as Boolean 'application flag for exiting Listener thread
Dim mReceiver as UdpClient 'a connection instance
...
Private Sub Listener()
While mListening
Try
Dim reply = mReceiver.Receive()
Catch ex As Exception
'execution goes here when mReceiver.Close() called
End Try
End While
End Sub
The app sets mListening and starts the Listener thread.
When the app needs to "unblock" mReceiver, it calls mReceiver.Close() and handles it accordingly. I've used this scheme without any problems. I'm using VS 2019 and .NET v4.7

what's different between the Blocked and Busy Waiting?

I known the implement of Busy Waiting. it's a death loop like this:
//main thread
while (true) {
msg = msgQueue.next();
msg.runnable.run();
}
//....msg queue
public Message next() {
while (true) {
if (!queue.isEmpty()) {
return queue.dequeue();
}
}
}
so, the method "next()" just looks like blocked, actually it runs all the time.
this was called "busy waiting" on book.
and what's the "process blocked"? what about its implement details?
is a death loop too? or some others? like signal mechanism?
For instance:
cat xxx | grep "abc"
process "cat" read a file and output them.
process "grep" waiting for input from "cat".
so before the "cat" output data, "grep" should be blocked, waiting for input and go on.
what details about this "blocked", a death loop read the input stream all the time? or really stop running, waiting a signal to wake up it to run?
The difference is basically in what happens to the process:
1. Busy Waiting
A process that is busy waiting is essentially continuously running, asking "Are we there yet? Are we there yet? How about now, are we there yet?" which consumes 100% of CPU cycles with this question:
bool are_we_there = false;
while(!are_we_there)
{
// ask if we're there (without blocking)
are_we_there = ask_if_we_are_there();
}
2. A process that is blocked (or that blocks)
A process that is blocked is suspended by the operating system and will be automatically notified when the data that it is waiting on becomes available. This cannot be accomplished without assistance from the operating system.
And example is a process that is waiting for a long-running I/O operation, or waiting for a timer to expire:
// use a system call to create a waitable timer
var timer = CreateWaitableTime()
// use another system call that waits on a waitable object
WaitFor(timer); // this will block the current thread until the timer is signaled
// .. some time in the future, the timer might expire and it's object will be signaled
// causing the WaitFor(timer) call to resume operation
UPDATE
Waitable objects may be implemented in different ways at the operating system level, but generally it's probably going to be a combination of hardware timers, interrupts and lists of waitable objects that are registered with the operating system by client code. When an interrupt occurs, the operating system's interrupt handler is called which in turn will scan though any waitable objects associated with that event, and invoke certain callback which in turn will eventually signal the waitable objects (put them in a signaled state). This is an over-simplification but if you'd like to learn more you could read up on interrupts and hardware timers.
When you say "a process is blocked" you actually mean "a thread is blocked" because those are the only schedulable entities getting CPU time. When a thread is busy waiting, it wastes CPU time in a loop. When a thread is blocked, the kernel code inside the system call sees that data or lock is not immediately available so it marks the thread as waiting. It then jumps to the scheduler which picks up another thread ready for execution. Such a code in a blocking system call might look like this:
100: if (data_available()) {
101: return;
102: } else {
103: jump_to_scheduler();
104: }
Later on the thread is rescheduled and restarts at line 100 but it immediately gets to the else branch and gets off the CPU again. When data becomes available, the system call finally returns.
Don't take this verbatim, it's my guess based on what I know about operating systems, but you should get the idea.

What happens when a thread makes kernel disable the interrupts and then that thread goes to sleep

I have this kernel code where I disable the interrupt to make this lock acquire operation atomic, but if u see the last else condition i.e. when lock is not available thread goes to sleep and interrupts are enable only after thread comes back from sleep. My question is so interrupts are disabled for whole OS until this thread comes out of sleep?
void Lock::Acquire()
{
IntStatus oldLevel = interrupt->SetLevel(IntOff); // Disabling the interrups to make the following statements atomic
if(lockOwnerThread == currentThread) //Checking if the requesting thread already owns lock
{
//printf("SM:error:%s already owns the lock\n",currentThread->getName());
DEBUG('z', "SM:error:%s already owns the lock\n",currentThread->getName());
(void) interrupt->SetLevel(oldLevel);
return;
}
if(lockOwnerThread==NULL)
{
lockOwnerThread = currentThread; // Lock owner ship is given to current thread
DEBUG('z', "SM:The ownership of the lock %s is given to %s \n",name,currentThread->getName());
}
else
{
DEBUG('z', "SM:Adding thread %s to request queue and putting it to sleep\n",currentThread->getName());
queueForLock->Append((void *)currentThread); // Lock is busy so add the thread to queue;
currentThread->Sleep(); // And go to sleep
}
(void) interrupt->SetLevel(oldLevel); // Enable the interrupts
}
I don't know the NACHOS and I would not make any assumptions on my own. So you have to test it.
The idea is simple. If this interrupt enable/disable functionality is local to the current process context then the following should happen when you call Sleep():
the process is marked as not-running, i.e. it is excluded from the list of processes the scheduler will consider to give a CPU time. Then the Sleep() function enforces the scheduler to do it's regular work - to find a process to run. If the list of running processes is not empty, the scheduler picks up a next available process and makes a context switch to this process. After this the state of interrupt management is restored from this new context.
If there are no processes to run then scheduler enters the Idle loop state and usually enables the interrupts. While the scheduler is in Idle loop it continues to poll the queue of the running processes until it get something to schedule.
Your process will get the control when it will be marked as running again. This could happen if some other process calls WakeUp() (or a like, as I mentioned the API is unknown to me)
When the scheduler will pick up your process to switch to it performs the usual (for your system) context switch that has the interrupts enabled flag set to false, so the execution continues at statement after the Sleep() call with interrupts disabled.
If the assumptions above are incorrect and the interrupts enabled flag is global, then there are two possibilities: either the system hangs as it can't serve the interrupts, or it has some workaround for such a situations.
So, you need to try. The best way is to read the kernel sources of course, if you have the access.))

Cancel thread with read() operation on serial port

in my Cocoa project, I communicate with a device connected to a serial port. Now, I am waiting for the serial device to send a particular message of some bytes. For the read operation (and the reaction for once the desired message has been received), I created a new thread. On user request, I want to be able to cancel the thread.
As Apple suggests in the docs, I added a flag to the thread dictionary, periodically check if the flag has been set and if so, call [NSThread exit]. This works fine.
Now, the thread may be stuck waiting for the serial device to finally send the 12 byte message. The read call looks like this:
numBytes = read(fileDescriptor, buffer, 12);
Once the thread starts reading from the device, but no data comes in, I can set the flag to tell the thread to finish, but the thread is not going to read the flag unless it finally received at least 12 bytes of data and continues processing.
Is there a way to kill a thread that currently performs a read operation on a serial device?
Edit for clarification:
I do not insist in creating a separate thread for the I/O operations with the serial device. If there is a way to encapsulate the operations such that I am able to "kill" them if the user presses a cancel button, I am perfectly happy.
I am developing a Cocoa application for desktop Mac OS X, so no restrictions regarding mobile devices and their capabilities apply.
A workaround would be to make the read function return immediately if there are no bytes to read. How can I do this?
Use select or poll with a timeout to detect when the descriptor is ready for reading.
Set the timeout to (say) half a second and call it in a loop while checking to see if your thread should exit.
Asynchronous thread cancellation is almost always a bad idea. Try to stick with event-driven interfaces (and, if necessary, timeouts).
This is exactly what the pthread_cancel interface was designed for. You'll want to wrap the block with read in pthread_cleanup_push and pthread_cleanup_pop in order that you can safely clean up if the thread is cancelled, and also disable cancellation (with pthread_setcancelstate) in other code that runs in this thread that you don't want to be cancellable. This can be a pain if proper cleanup would involve multiple call frames; it essentially forces you to use pthread_cleanup_push at every call level and structure your thread code like C++ or Java with try/catch style exception handling.
An alternative approach would be to install a signal handler for an otherwise-unused signal (like SIGUSR1 or one of the realtime signals) without the SA_RESTART flag, so that it interrupts syscalls with EINTR. The signal handler itself can be a complete no-op; the only purpose of it is to interrupt things. Then you can use pthread_kill to interrupt the read (or any other syscall) in a particular thread. This has the advantage that you don't have to switch your code to using C++/Java-type idioms. You can handle the EINTR error by checking a flag (indicating whether the thread was requested to abort) and resume the read if the flag is not set, or return an error code that causes the caller to clean up and eventually pthread_exit.
If you do use interrupting signal handlers, make sure all your syscalls that can return EINTR are wrapped in loops that retry (or check the abort flag and optionally retry) on EINTR. Otherwise things can break badly.

Blocking or sleeping an interrupt handler

Assume:
1) Multi-cpu environment
2) Process that gets interrupted, is the same process that executes the interrupt handler, so I guess technically nothing gets interrupted except what the process was doing before, but it is still executing as it is executing the handler.
3) There is no top or bottom half, when an interrupt takes place the handler is invoked, executes, then return from interrupt, simple as that.
Why would sleeping the handler (puts in sleep queue, context switch to next runnable process) be a bad idea?
Pls refer to Why kernel code/thread executing in interrupt context cannot sleep?
I just posted answer. Hope it makes sense for you.