For Programmers: Free Programming Magazines  


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;
}


Bjorn Reese

2005-11-16, 7:02 pm

Gianni Mariani wrote:

> int g_winch_needed = 0;


To avoid undefined behavior make that:

volatile sig_atomic_t g_winch_needed = 0;

See:

http://www.opengroup.org/onlinepubs...ons/signal.html

--
mail1dotstofanetdotdk
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com