Triggering Signal Handler For I/O - c

Using C on Linux, how would I go about triggering a signal handler every time I write data to a buffer using the write() function. The handler will be reading all data written to the buffer at the time of execution.

Sockets support this by enabling async mode on the socket file descriptor. On Linux this is done using fcntl calls:
/* set socket owner (the process that will receive signals) */
fcntl(fd, F_SETOWN, getpid());
/* optional if you want to receive a real-time signal instead of SIGIO */
fnctl(fd, F_SETSIG, signum);
/* turn on async mode -- this is the important part which enables signal delivery */
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_ASYNC);

Use pipe() with O_ASYNC and you'll recieve a SIGIO on the read end of the pipe whenever there's new data on the pipe.

I don't 100% understand what you are trying to do, BUT
select might be what you need. waiting for data to be written to a file/pipe. You can use it to do/simulate asynchronous I/O.

If the file descriptor being used with write() is not for a FIFO, pipe (as suggested by Ken Bloom), asynchronous socket (as suggested by mark4o), and does not otherwise cause a signal (i.e. SIGIO), I suppose you could use raise() to send a signal to the current process after writing data to the buffer. Depending on what you are actually trying to achieve, this may not be the best solution.
Update
If I understand you correctly, you want to write to a file, have a SIGIO signal generated on completion of the write, and then read the data back from within the signal handler. It seems you want to use asynchronous I/O for a file.
In Asynchronous I/O on linux or: Welcome to hell, the author describes various asynchronous I/O techniques on Linux, including using the SIGIO signal. The SIGIO signal technique cannot be used with regular files.
Even though the author of the previously mentioned article doesn't think highly of the POSIX AIO API provided in the 2.6 kernel, you may want to look into it anyway as it can be used to provide notification of asychronous read/write completion to a regular file through signals and function callbacks.
In Boost application performance using asynchronous I/O, the author provides an overview of basic Linux I/O models before introducing the AIO API.

Related

Correctly processing Ctrl-C when using poll()

I am making a program, that runs like a server, so it is constantly running poll. I need to process both Ctrl-C and Ctrl-D. And while Ctrl-D is pretty easy to work with when using poll (you just also poll for POLLIN on stdin), I cannot come up with a pretty solution for signals. Do I need to create a dummy file to which my signal handler will write something when it's time to exit, or would pipes fit this purpose nicely?
As commented by Dietrich Epp, a usual way of handling this is the "pipe to self" trick. First, at initialization time, you set up a pipe(7): you'll call pipe(2) and you keep both read and write file descriptors of that pipe in some (e.g. global) data. Your signal handler would just write(2) onto the write-end fd some bytes (perhaps a single 0 byte ...). And your event loop around poll(2) (or the older select(2), etc...) would react by read(2)-ing bytes when the read-end file descriptor has some data.
This pipe to self trick is common and portable to all POSIX systems, and recommended e.g. by Qt.
The signalfd(2) system call is Linux specific (e.g. you don't have that on MacOSX). Some old Linux kernels might not have it.
Be aware that the set of functions usable inside a signal handler is limited to async-signal-safe functions - so you are allowed to use write(2) but forbidden to use fprintf or malloc inside a signal handler. Read carefully signal(7) and signal-safety(7).
signalfd is what you are after - connect it to SIG_INT and you can poll for ctrl+c – see the example in the link provided (quite down the page – actually, they are catching ctrl+c there...).

How to change Linux interrupt timer for tcsetattr()

I am using serial port, and while communicating with this, i have to change the configuration using tcsetattr() with TCSDRAIN mode.
TCSADRAIN
The change should take place after all output written to fd has been read by the master pseudoterminal. Use this value when changing terminal attributes that affect output.
And while calling tcsetattr() with TCSDRAIN, if there still remain output data in buffer, Linux seems blocked and check the buffer again after a some interrupt time to change a configuration.
I tested for this like below
First Normall Case
write data to serial
change configuration using tcsetattr()
there is a remaining data in output buffer
the process blocked during regular interval, for example 20ms
wake up.
Second Case
write data to serial
take sleep() manually for 5ms, it means give enough time to clear output to Linux
there is no remaining data
change configuration using tcsetattr()
there is no block
And for me the interrupt time is too long to do what i want
How can i change this interrupt timer interval?
(in Ubuntu and raspberrypi)
I do not think that the .cc[VTIME] field of the termios structure affects the flush timeout, if that's what you are asking. As far as I know, it only affects the read() behaviour.
However, there are several ways you can control the interval the kernel tries to drain/flush, before giving up.
One option is to use fcntl(fd, F_SETFL, O_NONBLOCK) to (temporarily) set the descriptor to non-blocking state, and use clock_gettime(CLOCK_MONOTONIC, &now) and nanosleep() to retry tcsetattr(fd, TCSADRAIN, &attrs) a few times over a suitable time interval, until it succeeds. Then revert the descriptor to normal mode using fcntl(fd, F_SETFL, 0). If the tcsetattr() calls failed with errno == EWOULDBLOCK || errno == EAGAIN, use tcsetattr(fd, TCSANOW, &attrs) to discard all unread/unsent data.
Note that I have not tested the above on RPi! It might not work on some specific architectures/serial port drivers, as it is possible to hardcode the flush/drain interval into the driver and disregard the fact that the descriptor is in non-blocking mode. That would be a bug, however, and is fixable with a kernel patch. (In other words, this should work, but some serial port drivers may be crappy, and ignore the nonblocking nature above, and will block until some unspecified interval.)
Another option is to use a timer to raise a signal. If you install a function to handle that signal without the SA_RESTART flag, the delivery of the signal will interrupt the blocking tcdrain()/tcflush()/tcsetattr() call. (If the process uses multiple threads, the signal should be blocked in all other threads, as otherwise the kernel will just pick one of the process' threads to deliver the signal. If it is not the thread in a blocking call, the blocking call will not be interrupted.)
Because signals are a very reliable method to interrupt most syscalls and library functions (see section Interruption of system calls and library functions by signal handlers in man 7 signal -- termios functions are equivalent to ioctl() calls in Linux), I personally prefer to have a separate thread do nothing but maintain these timeouts. Such a thread is very lightweight, and does not consume CPU time unless a timeout elapses or is added. I can also have multiple concurrent timeouts, with a simple interface to check, cancel, and add timeouts, which makes it easier to design the rest of the application to be robust and efficient.

OpenSSL crashes when freeing a closed socket with pending data [duplicate]

I have a small server program that accepts connections on a TCP or local UNIX socket, reads a simple command and (depending on the command) sends a reply.
The problem is that the client may have no interest in the answer and sometimes exits early. So writing to that socket will cause a SIGPIPE and make my server crash.
What's the best practice to prevent the crash here? Is there a way to check if the other side of the line is still reading? (select() doesn't seem to work here as it always says the socket is writable). Or should I just catch the SIGPIPE with a handler and ignore it?
You generally want to ignore the SIGPIPE and handle the error directly in your code. This is because signal handlers in C have many restrictions on what they can do.
The most portable way to do this is to set the SIGPIPE handler to SIG_IGN. This will prevent any socket or pipe write from causing a SIGPIPE signal.
To ignore the SIGPIPE signal, use the following code:
signal(SIGPIPE, SIG_IGN);
If you're using the send() call, another option is to use the MSG_NOSIGNAL option, which will turn the SIGPIPE behavior off on a per call basis. Note that not all operating systems support the MSG_NOSIGNAL flag.
Lastly, you may also want to consider the SO_SIGNOPIPE socket flag that can be set with setsockopt() on some operating systems. This will prevent SIGPIPE from being caused by writes just to the sockets it is set on.
Another method is to change the socket so it never generates SIGPIPE on write(). This is more convenient in libraries, where you might not want a global signal handler for SIGPIPE.
On most BSD-based (MacOS, FreeBSD...) systems, (assuming you are using C/C++), you can do this with:
int set = 1;
setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
With this in effect, instead of the SIGPIPE signal being generated, EPIPE will be returned.
I'm super late to the party, but SO_NOSIGPIPE isn't portable, and might not work on your system (it seems to be a BSD thing).
A nice alternative if you're on, say, a Linux system without SO_NOSIGPIPE would be to set the MSG_NOSIGNAL flag on your send(2) call.
Example replacing write(...) by send(...,MSG_NOSIGNAL) (see nobar's comment)
char buf[888];
//write( sockfd, buf, sizeof(buf) );
send( sockfd, buf, sizeof(buf), MSG_NOSIGNAL );
In this post I described possible solution for Solaris case when neither SO_NOSIGPIPE nor MSG_NOSIGNAL is available.
Instead, we have to temporarily suppress SIGPIPE in the current thread that executes library code. Here's how to do this: to suppress SIGPIPE we first check if it is pending. If it does, this means that it is blocked in this thread, and we have to do nothing. If the library generates additional SIGPIPE, it will be merged with the pending one, and that's a no-op. If SIGPIPE is not pending then we block it in this thread, and also check whether it was already blocked. Then we are free to execute our writes. When we are to restore SIGPIPE to its original state, we do the following: if SIGPIPE was pending originally, we do nothing. Otherwise we check if it is pending now. If it does (which means that out actions have generated one or more SIGPIPEs), then we wait for it in this thread, thus clearing its pending status (to do this we use sigtimedwait() with zero timeout; this is to avoid blocking in a scenario where malicious user sent SIGPIPE manually to a whole process: in this case we will see it pending, but other thread may handle it before we had a change to wait for it). After clearing pending status we unblock SIGPIPE in this thread, but only if it wasn't blocked originally.
Example code at https://github.com/kroki/XProbes/blob/1447f3d93b6dbf273919af15e59f35cca58fcc23/src/libxprobes.c#L156
Handle SIGPIPE Locally
It's usually best to handle the error locally rather than in a global signal event handler since locally you will have more context as to what's going on and what recourse to take.
I have a communication layer in one of my apps that allows my app to communicate with an external accessory. When a write error occurs I throw and exception in the communication layer and let it bubble up to a try catch block to handle it there.
Code:
The code to ignore a SIGPIPE signal so that you can handle it locally is:
// We expect write failures to occur but we want to handle them where
// the error occurs rather than in a SIGPIPE handler.
signal(SIGPIPE, SIG_IGN);
This code will prevent the SIGPIPE signal from being raised, but you will get a read / write error when trying to use the socket, so you will need to check for that.
You cannot prevent the process on the far end of a pipe from exiting, and if it exits before you've finished writing, you will get a SIGPIPE signal. If you SIG_IGN the signal, then your write will return with an error - and you need to note and react to that error. Just catching and ignoring the signal in a handler is not a good idea -- you must note that the pipe is now defunct and modify the program's behaviour so it does not write to the pipe again (because the signal will be generated again, and ignored again, and you'll try again, and the whole process could go on for a long time and waste a lot of CPU power).
Or should I just catch the SIGPIPE with a handler and ignore it?
I believe that is right on. You want to know when the other end has closed their descriptor and that's what SIGPIPE tells you.
Sam
What's the best practice to prevent the crash here?
Either disable sigpipes as per everybody, or catch and ignore the error.
Is there a way to check if the other side of the line is still reading?
Yes, use select().
select() doesn't seem to work here as it always says the socket is writable.
You need to select on the read bits. You can probably ignore the write bits.
When the far end closes its file handle, select will tell you that there is data ready to read. When you go and read that, you will get back 0 bytes, which is how the OS tells you that the file handle has been closed.
The only time you can't ignore the write bits is if you are sending large volumes, and there is a risk of the other end getting backlogged, which can cause your buffers to fill. If that happens, then trying to write to the file handle can cause your program/thread to block or fail. Testing select before writing will protect you from that, but it doesn't guarantee that the other end is healthy or that your data is going to arrive.
Note that you can get a sigpipe from close(), as well as when you write.
Close flushes any buffered data. If the other end has already been closed, then close will fail, and you will receive a sigpipe.
If you are using buffered TCPIP, then a successful write just means your data has been queued to send, it doesn't mean it has been sent. Until you successfully call close, you don't know that your data has been sent.
Sigpipe tells you something has gone wrong, it doesn't tell you what, or what you should do about it.
Under a modern POSIX system (i.e. Linux), you can use the sigprocmask() function.
#include <signal.h>
void block_signal(int signal_to_block /* i.e. SIGPIPE */ )
{
sigset_t set;
sigset_t old_state;
// get the current state
//
sigprocmask(SIG_BLOCK, NULL, &old_state);
// add signal_to_block to that existing state
//
set = old_state;
sigaddset(&set, signal_to_block);
// block that signal also
//
sigprocmask(SIG_BLOCK, &set, NULL);
// ... deal with old_state if required ...
}
If you want to restore the previous state later, make sure to save the old_state somewhere safe. If you call that function multiple times, you need to either use a stack or only save the first or last old_state... or maybe have a function which removes a specific blocked signal.
For more info read the man page.
Linux manual said:
EPIPE The local end has been shut down on a connection oriented
socket. In this case the process will also receive a SIGPIPE
unless MSG_NOSIGNAL is set.
But for Ubuntu 12.04 it isn't right. I wrote a test for that case and I always receive EPIPE withot SIGPIPE. SIGPIPE is genereated if I try to write to the same broken socket second time. So you don't need to ignore SIGPIPE if this signal happens it means logic error in your program.

Waiting for multiple events without polling

I'm new to linux programming and not entirely familiar with all the synchronization facilities so I'd like to ask more knowledgeable people how they might go about solving this problem.
I have a single thread that I would like to run through a loop. The stopping point in the loop will be a read operation on a socket. I want the read operation to block for some period of time and then timeout. However, I need a way unblock the thread from the read, if some event needs attention. The "event" could be any one of a number of different things so I need some way to tell the thread what cause the read to unblock.
I know that you can unblock a blocked read with a signal but I'm not sure how that's done.
See the select() system call.
This is especially useful for waiting for multiple file channels.
You can set timeout of socket operation. Example:
struct timeval timeout;
timeout.tv_sec = TIMEOUT_SEC;
timeout.tv_usec = TIMEOUT_MSEC;
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
/* now receive msg */
recvmsg(sock_fd, &msg, 0);
When you want to make your socket blocking, do:
timeout.tv_sec = 0;
timeout.tv_usec = 0;
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
epoll seems to be the way to go:
The epoll API performs a similar task to poll(2): monitoring multiple
file descriptors to see if I/O is possible on any of them. The epoll
API can be used either as an edge-triggered or a level-triggered inter‐
face and scales well to large numbers of watched file descriptors. The
following system calls are provided to create and manage an epoll
instance:
man epoll for more info. You might want to see "Example for Suggested Usage" section on manual.
See also epoll vs select
Sounds like you want to use select() as others have mentioned, but you also want a way to interrupt it when a "message" of some sort is available. A typical way of interrupting a select() is to use the self pipe trick. Basically you create a pipe() and also select() on the read file descriptor of the pipe. When a message arrives in the queue maintained by your program, write a byte to the pipe. This will cause your select call to return and you'll be able to check to see if your pipe is ready for reading. If it is then you know you have a message to process (whatever that is in your context), so you process it and then go back to select(). Better yet, you could have your pipe actually be your message queue. If you just use the pipe as a way to signal that messages are on your queue, make sure you actually read() the bytes out of your pipe each time through, or it will fill up eventually and block you from writing more notifications to it.
Although, as others have mentioned, why not just have one thread service your queue and do your writes to the socket, while another thread does the reads? Probably a lot simpler.
Perhaps these two libraries may be of use to you:
libev
libuv
They both use the event-driven paradigm on one or more threads (if so desired). Of course, you can implement your own event-driven framework using already mentioned APIs and conditional variables, but that might be more work than necessary.

inotify 'main loop'

I am using inotify with "interupt io" by setting the O_ASYNC flag on the
inotify file descriptor and then using fcntl(inotifyfd, F_SETOWN, getpid())
coupled with a signal(sighandler, SIGIO) call, all from a single process,
in order to set up an inotify file descriptor event handler.
The idea is to have inotify's file descriptor generate the SIGIO signal (via the O_ASYNC flag set) and have teh signal(..) registered handler handle the SIGIO signals
as they are emitted thus avoiding polling the inotify file descriptor.
After the initial setup and signal handler setting the process has nothing to do
and would normally exit.
I need the same process to remain idle after the setup as it acts as a daemon awaiting the SIGIO signals. This is where I am looking for help.
How can I idle the process to take the very least amount of cpu resources?
If your process is going to remain idle until it sees inotify events, then you're severely overcomplicating things.
Just do a normal blocking read() on the inotify file descriptor. Your process will wake up when there's an inotify event. If you want to block-with-timeout, so you can periodically check for something else, use select().
In general, I find that if the answer is "signals" then you've probably asked the wrong question :)
One easy way is to just sleep(3) for a very large amount of time. Since signals wake up the process, you need to put the sleep in a loop:
while(1)
sleep(1000);
The more correct way is probably to use sigsuspend(2):
sigsuspend(NULL);
Just loop on a sigsuspend(); , or even sleep() in this situation. Keep in mind though, that one SIGIO signal might one or more IO events are available.

Resources