Home > Archive > Unix Programming > November 2005 > Need a lock to return data from a signal handler?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Need a lock to return data from a signal handler?
|
|
| Scott V. McGuire 2005-11-16, 3:59 am |
| Hi all,
I got to this question trying to figure out how to deal with SIGWINCH
in a full screen terminal application, but I think it applies to
signals in general.
If I get data in a signal handler which I need to pass back to the
rest of the program, say the new terminal size, how do I do that
safely? At the time of the interrupt, the program could have been in
the middle of working with the data that I need to change. This seems
to be exactly the same problem I would have in a multithreaded program
in which case the answer is obvious: use a mutex or similar locking
mechanism. But I don't find locking in the examples of signal
handling that I've looked at. I suppose I could use a pthreads mutex,
but I don't think that most non-threaded programs are linked against
pthreads and it is hard to believe that they all handle signals
undafely.
Can anyone shed some light on this?
Thanks,
--
Scott V. McGuire
| |
| Gianni Mariani 2005-11-16, 3:59 am |
| Scott V. McGuire wrote:
> Hi all,
>
> I got to this question trying to figure out how to deal with SIGWINCH
> in a full screen terminal application, but I think it applies to
> signals in general.
>
> If I get data in a signal handler which I need to pass back to the
> rest of the program, say the new terminal size, how do I do that
> safely? At the time of the interrupt, the program could have been in
> the middle of working with the data that I need to change. This seems
> to be exactly the same problem I would have in a multithreaded program
> in which case the answer is obvious: use a mutex or similar locking
> mechanism. But I don't find locking in the examples of signal
> handling that I've looked at. I suppose I could use a pthreads mutex,
> but I don't think that most non-threaded programs are linked against
> pthreads and it is hard to believe that they all handle signals
> undafely.
>
> Can anyone shed some light on this?
There are very few things you can do safely in a signal handler.
a) You can't allocate memory
b) You can't take a lock
c) You CAN set a global variable
About the only thing you can do is set a flag or perform a "safe" system
call (like write to a pipe).
Below is some code I wrote quite a while ago (tweaked a little
recently). Hope this helps.
int g_winch_needed = 0;
int perform_winch()
{
struct winsize ws;
if ( ioctl( 0, TIOCGWINSZ, &ws ) != -1) {
if ( current_nrow != ( ws.ws_row - 1 ) ) {
new_row_size( TRUE, ws.ws_row );
}
if ( current_ncol != ws.ws_col ) {
new_col_size( TRUE, ws.ws_col );
}
}
}
void window_change( int l_unused )
{
g_winch_needed = 1;
signal( SIGWINCH, window_change );
}
int check_winch()
{
if ( g_winch_needed )
{
perform_winch();
}
}
int has_buffered_chars( FILE * l_fs )
{
/* this is system dependant - we need to know if */
/* there are any chars in the FILE that are being */
/* bufferered */
#if IRIX
if ( l_fs->_cnt != 0 ) {
return TRUE;
}
#else
#if defined(__CYGWIN__)
if ( l_fs->_r > 0 ) {
return TRUE;
}
#else /* linux */
if ( l_fs->_IO_read_ptr < l_fs->_IO_read_end ) {
return TRUE;
}
#endif
#endif
return FALSE;
}
unsigned WaitForFile( FILE * i_fs )
{
fd_set readfds;
struct timeval * tval = 0;
int rez;
unsigned retval = 0;
FD_ZERO( &readfds );
FD_SET( fileno( i_fs ), &readfds );
rez = select(
1 + fileno( i_fs ),
&readfds,
(fd_set *) 0,
(fd_set *) 0,
tval
);
if ( rez == -1 )
{
if ( errno == EINTR )
{
return WAIT_FOR_INTR;
}
return 0;
}
retval = 0;
if ( FD_ISSET( fileno( i_fs ), &readfds ) )
{
retval |= WAIT_FOR_FILE_READY;
}
return retval;
}
int GetChar()
{
int ch;
int i = 0;
do {
if ( i ++ > 10 ) {
return -1;
}
check_winch();
if ( has_buffered_chars( stdin ) )
{
ch = fgetc( stdin );
} else {
fflush( stdout );
fflush( stderr );
while ( ! ( WaitForFile( stdin ) & WAIT_FOR_FILE_READY ) )
{
check_winch();
}
ch = fgetc( stdin );
}
} while ( ch == -1 );
return ch;
}
| |
|
|
|
|
|