Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing a message in the terminal from which signal was sent

Tags:

c++

linux

tty

My process in running as daemon. I want to reload the configuration using signal. The problem is that if configuration is wrong it should error message in the tty form which signal was sent.

  1. Is there a way to do this?
  2. Is it recommended way?

If it is not recommended way. What will be a more appropriate way to check if it was successful or not?

like image 476
Vivek Goel Avatar asked Jan 16 '23 00:01

Vivek Goel


2 Answers

For getting pid of signal source, you need to use sa_sigaction instead of sa_handler when you set signal handlers:

static pid_t g_killer_pid = 0;

static void signal_handler( int num, siginfo_t *info, void* blabla )
{
    g_killer_pid = info->si_pid;
}

int main(void)
{    
    struct sigaction sa;

    memset( &sa, 0, sizeof(sa) );
    sa.sa_sigaction = &signal_handler;
    sa.sa_flags = SA_SIGINFO;
    sigaction( SIGTERM, &sa, NULL );
    sigaction( SIGINT,  &sa, NULL );

    pause();
    hello_killer( g_killer_pid );

    return 0;
}

Now you have pid of the source process.

For getting terminal id of the source process is not so simple. One way is read it from proc/<pid>/stat file. One number in the file is tty_nr. tty_nr is little bit strange for me, so I don't know is this even portable stuff. But it holds minor number, that can be used for opening correct terminal for writing:

static void hello_killer( pid_t killer )
{
    char filename[200];
    FILE* fil;
    FILE* out;
    int tty_nr;

    sprintf( filename, "/proc/%ld/stat", (long int)killer );
    fil = fopen( filename, "r" );
    if( fil )
    {
        if( fscanf( fil, "%*s %*s %*s %*s %*s %*s %d ", &tty_nr ) == 1 )
        {
            sprintf( filename, "/dev/pts/%d", (tty_nr & 0xF) | ((tty_nr >> 20) & 0xFFF) );

            out = fopen( filename, "a" );
            if( out )
            {
                fprintf( out, "Hello!\n" );
                fclose( out );
            }
        }
        fclose( fil );
    }
}

I am not sure is that /dev/pts trick correct/best way to do it. But it seems to work in my Linux box:

~ # killall temp_test
Hello!
~ #
like image 107
SKi Avatar answered Jan 28 '23 14:01

SKi


I'm guessing you something like catching SIGUSR1 and then reload the configuration?

You should remember that signal handlers should be as small and quick as possible, and not do something that can cause another signal. So basically you should refrain from I/O as much as possible. What is probably the best way to do this is to have a very simple signal handler that only sets a flag, then in your main loop you check for this flag and then reload your configuration in the context of your main thread. There you can output to the console all you want.

like image 37
Some programmer dude Avatar answered Jan 28 '23 13:01

Some programmer dude