Showing a message in the terminal from which signal was sent - c++

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.
Is there a way to do this?
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?

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!
~ #

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.

You can do this, but there's no trivial way to do it. You need to arrange a mechanism for the daemon to feedback to the process sending the signal.
Some possible ways of doing that include:
Write the (timestamped) result to a file in a predetermined location.
Have the daemon maintain a shared memory segment with the information in a known structure.
Have the daemon listen on a named pipe/socket of some sort and give out feedback that way. (You could also send the reload command via that channel).
Have the thing that sends the signal and the daemon link against a shared library so that both are capable of validating the configuration file. Validate the file before raising the signal.
Of those a named pipe would be my first choice I think - you can restrict access to it with normal permissions and it's the easiest to make robust and correct.

I doubt, that you can determine the source of the signal and even, if you could so, it don't have to be a terminal. What about using a simple tcp/ip protocol? Accept tcp/ip connections on a special port. Read a command until a first new line. If that command is "reconfigure", do the reconfiguration and send a message over the established TCP/IP connection.

Related

C++: Calling sendmail from pthread results in Broken Pipe

I'm trying to send an e-mail with sendmail in a separate pthread. This code works 99.9% of the time.
void* emailClientThreadFct(void* emailClientPtr)
{
EmailClient* emailClient = static_cast<EmailClient*>(emailClientPtr);
try
{
emailClient->Send();
}
catch (const exception& excep)
{
SYSLOG_ERROR("E-mail client exception: %s", excep.what());
}
delete emailClient;
return NULL;
}
// Send email for current output in a separate thread
pthread_t emailThread;
pthread_attr_t attr;
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&emailThread, &attr, emailClientThreadFct, emailClientObj);
0.1% of the time, I get the error fwrite error Broken Pipe when I do the following call. From what I read, Broken Pipe (EPIPE 32) is usually a receiver problem, but sendmail is a local process... Could it be that I'm sending too much data to fwrite? Or that I'm doing something bad in my pthread instanciation? Or has sendmail crashed?
void EmailClient::Send() const
{
// Flush all open output streams, as recommended by popen man page
fflush(NULL);
string popen_command = "sendmail -t -oi >/dev/null 2>&1");
// Open pipe to Mail Transport Agent (MTA)
errno = 0;
FILE* stream = popen(popen_command.c_str(), "w");
if (stream == NULL)
{
throw exception("Cannot send email popen");
}
errno = 0;
if (fwrite(message.data(), message.size(), 1, stream) < 1)
{
pclose(stream);
throw exception("fwrite error ", strerror(errno));
}
// Close MTA
errno = 0;
if (pclose(stream) == -1)
printf("\"Error closing the MTA pipe (%s)\"", strerror(errno))
}
EPIPE means that the other end (the process you are writing to) has died. This could happen if there is a fork failure (popen invokes the shell, so there is another subprocess involved) because there are temporarily too many processes in the system. A more direct cause would be sendmail failing and exiting prematurely, before reading all of standard input, say due to malformed email headers.
popen is unfortunately not a very reliable interface. You might be better off using fork/execve or posix_spawn, either with a temporary file for the input or I/O multiplexing using poll, just to be able to capture any error that sendmail might generate. Alternatively, you could try to call sendmail with -oee, which is supposed to report any errors by email, but it won't help if the creation of the sendmail itself fails.

Creating non blocking pipes to child that does not block and can be reused

I am trying to create a inter process communication bus using pipes.
I can send messages to the client, and i can receive messages at the client.
I also tried to create another pipe which goes the other way, child-> parent.
However I need this communication to be non blocking and I want to send messages in both directions with some undefined time gap in between.
It appears i can not send more then one message, I take it it is due to the fclose(); closing the stream, however if i remove the close, the program stops working...
How can I make this code nonblocking two way parent -> child communication through pipes?
Later I want to connect a child-binary using exec(), and connecting this binary's stdin, stdout to my parent, so that I can pass messages to the stdin of the child and retrieve answers through the "childParent" descriptor.
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define READ_SIDE 0
#define WRITE_SIDE 1
/* Read characters from the pipe and echo them to stdout. */
void
read_from_pipe (int file)
{
FILE *stream;
int c;
stream = fdopen (file, "r");
while ((c = fgetc (stream)) != EOF)
putchar (c);
fclose (stream);
}
/* Write some random text to the pipe. */
void
write_to_pipe (int file, char * message)
{
FILE *stream;
stream = fdopen (file, "w");
fprintf (stream, message);
//fprintf (stream, "goodbye, world!\n");
//Dont forget to close
fclose (stream);
}
void end(){
//kill process and close pipes
}
int
main (void)
{
pid_t pid;
int parentToChild[2];
int childToParent[2];
/* Create the pipes. */
if (pipe (parentToChild))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
if (pipe (childToParent))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
/* Create the child process. */
pid = fork ();
if (pid == (pid_t) 0)
{
/* This is the child process.
Close other end first. */
close(childToParent[READ_SIDE]);
close (parentToChild[WRITE_SIDE]);
read_from_pipe (parentToChild[READ_SIDE]);
write_to_pipe(childToParent[WRITE_SIDE], "Child sent message to parent");
return EXIT_SUCCESS;
}
else if (pid < (pid_t) 0)
{
/* The fork failed. */
fprintf (stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else
{
/* This is the parent process.
Close other end first. */
close(childToParent[WRITE_SIDE]);
close (parentToChild[READ_SIDE]);
write_to_pipe (parentToChild[WRITE_SIDE],"Parent sent message to child");
read_from_pipe(childToParent[READ_SIDE]);
//Send more messages...
return EXIT_SUCCESS;
}
}
UPDATE
It appears that sometimes the communication only happens one way, depending on which process gets to read/write first I guess.
There are several issues to be considered. First, pipes have a finite
maximum length (4096 was common in the distant past); any write to a
pipe which has more data in it than that will block, as will any read
from an empty pipe. These are fundamental to the way pipes work, so
when you speak of non-blocking, you have to take them into consideration
(or use asynchronous IO).
Second, if you really need to control things at this level, you might
want to consider using Posix level IO, rather than streams. If you do
use streams (either iostream or FILE*), then you have to take into
account the buffering they use. In particular, when you want to be sure
that the data is output to the pipe, you need to flush (fflush on
the FILE*). With regards to sending more than one message, and the
code not working without the fclose, replacing the fclose with
fflush should be all you need to fix this.
And while I'm at it: your use of fprintf for output is extremely
dangerous. If you're getting a message from an external source, and
(possibly) don't know what it contains, you should use fputs to output
it, or possibly something like fprintf( fd, "%s\n", message ) (if you
want to append a new line). As you've done it, if the message contains
a '%', strange things will happen. More generally, you should prefer
the much safer iostream, but for simple things like this, it doesn't
matter much. And for what you're actually doing, Posix level IO is
probably just as appropriate, or more so. With Posix level IO, you
don't get any formatting or buffering: but since you're not using the
formatting capabilities, and the buffering it part of your problem...

How to output to the currently visible terminal

I want to output some text as response to the signal SIGUSR1
I.e. a user sends kill -USR1 <pid> to a process started in background or in another terminal.
I would like to get some output in the terminal where kill was invoked.
How can I achieve this?
The comment of #BoBTFish is working. A possible pseudo C++ implementation:
// somewhere in code:
std::memset(&sa, 0, sizeof(struct sigaction));
sa.sa_sigaction = sh_dump;
sa.sa_flags = static_cast<int>(SA_SIGINFO); // <- important, else you'll get an invalid siginfo_t pointer
sigaction(SIGUSR1, &sa, NULL);
void sh_dump(int, siginfo_t *info, void *) {
if(info) {
// do some locking of your choice
char *p = NULL;
char sp[PATH_MAX] = "";
std::snprintf(sp, PATH_MAX, "/proc/%d/stat", info->si_pid);
int tty_nr = 0;
FILE *spf;
if((spf = std::fopen(sp, "r"))) {
int iDummy;
char cDummy, *sDummy;
// proc(5)
if(std::fscanf(spf, "%d %ms %c %d %d %d %d", &iDummy, &sDummy, &cDummy, &iDummy, &iDummy, &iDummy, &tty_nr)) {}
free(sDummy);
std::fclose(spf);
}
// see http://goo.gl/L0pGK1 for an implementation
if(!(p = ttynameCheckDir(static_cast<dev_t>(tty_nr), "/dev/pts"))) {
p = ttynameCheckDir(static_cast<dev_t>(tty_nr), "/dev");
}
std::ofstream out(p ? p : "/dev/null");
free(p);
if(out.is_open()) out << "HELLO" << std::endl;
// do some unlocking of your choice
}
}
prints HELLO on the terminal invoking kill -USR1 <pid>
EDIT: Using /proc/#/stat (Linux only)
To ensure you write to the controlling terminal there's a device /dev/tty just for this. It won't work if you are in a detached (no controlling terminal) process. Just open(2) it and write(2) Normally, stdin/stdout/stderr can be redirected, so to assure you are writing somewhere the user will see, open /dev/tty and write to it. /dev/tty predates from the ancient times of unix. It has been conserved for compatibility. It can be used also to get passwords and ensure you are not redirecting some file descriptor fed to the process.

run a process with c++, filtering output AND get result code AND get system errors, all together

I want to run another program from c++, redirecting its output to a file and return its result code.
But if I fail to run the program (incorrect path etc.) I want to know.
Here is my problem, how can I: redirect a file, get the result code of the program, get the errors of the system, all at once?
System(): returns the result and is easy to redirect, but there is no way to know if the result is a system error or the application result
posix_spawn(): I know if there is a system error, but how to get the application result code ?
Note that I don't control the code of the executed application
It's easy with Windows (sorry...) OpenProcess() function, what I need is OpenProcess() under linux.
Thanks
You will need to use the posix_spawn function.
The waitpid system call will help you to get the exit code.
See this question.
pid_t waitpid(pid_t pid, int *status, int options);
What you need to do is pretty match standard fork-exec call plus file redirection:
int pid = fork();
if( pid == -1 ) {
// process error here
}
if( pid == 0 ) {
int fd = open( "path/to/redirected/output", ... );
::close( 1 );
dup2( fd, 1 );
::close( fd );
exec...( "path to executable", ... );
// if we are here there is a problem
exit(123);
}
int status = 0;
waitpid( pid, &status, 0 );
// you get exit status in status
By exec... I mean one of the exec functions family (type "man 3 exec" for information), choose one that fits you better.
If you need to redirect error output do the same, but use descriptor 2. You may want to put waitpid() in the loop and check if it is not interrupted by signal.

popen simultaneous read and write [duplicate]

This question already has answers here:
Can popen() make bidirectional pipes like pipe() + fork()?
(6 answers)
Closed 3 years ago.
Is it possible to read and write to a file descriptor returned by popen. I have an interactive process I'd like to control through C. If this isn't possible with popen, is there any way around it?
As already answered, popen works in one direction. If you need to read and write, You can create a pipe with pipe(), span a new process by fork() and exec functions and then redirect its input and outputs with dup2(). Anyway I prefer exec over popen, as it gives you better control over the process (e.g. you know its pid)
EDITED:
As comments suggested, a pipe can be used in one direction only. Therefore you have to create separate pipes for reading and writing. Since the example posted before was wrong, I deleted it and created a new, correct one:
#include<unistd.h>
#include<sys/wait.h>
#include<sys/prctl.h>
#include<signal.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
int main(int argc, char** argv)
{
pid_t pid = 0;
int inpipefd[2];
int outpipefd[2];
char buf[256];
char msg[256];
int status;
pipe(inpipefd);
pipe(outpipefd);
pid = fork();
if (pid == 0)
{
// Child
dup2(outpipefd[0], STDIN_FILENO);
dup2(inpipefd[1], STDOUT_FILENO);
dup2(inpipefd[1], STDERR_FILENO);
//ask kernel to deliver SIGTERM in case the parent dies
prctl(PR_SET_PDEATHSIG, SIGTERM);
//replace tee with your process
execl("/usr/bin/tee", "tee", (char*) NULL);
// Nothing below this line should be executed by child process. If so,
// it means that the execl function wasn't successfull, so lets exit:
exit(1);
}
// The code below will be executed only by parent. You can write and read
// from the child using pipefd descriptors, and you can send signals to
// the process using its pid by kill() function. If the child process will
// exit unexpectedly, the parent process will obtain SIGCHLD signal that
// can be handled (e.g. you can respawn the child process).
//close unused pipe ends
close(outpipefd[0]);
close(inpipefd[1]);
// Now, you can write to outpipefd[1] and read from inpipefd[0] :
while(1)
{
printf("Enter message to send\n");
scanf("%s", msg);
if(strcmp(msg, "exit") == 0) break;
write(outpipefd[1], msg, strlen(msg));
read(inpipefd[0], buf, 256);
printf("Received answer: %s\n", buf);
}
kill(pid, SIGKILL); //send SIGKILL signal to the child process
waitpid(pid, &status, 0);
}
The reason popen() and friends don't offer bidirectional communication is that it would be deadlock-prone, due to buffering in the subprocess. All the makeshift pipework and socketpair() solutions discussed in the answers suffer from the same problem.
Under UNIX, most commands cannot be trusted to read one line and immediately process it and print it, except if their standard output is a tty. The reason is that stdio buffers output in userspace by default, and defers the write() system call until either the buffer is full or the stdio stream is closed (typically because the program or script is about to exit after having seen EOF on input). If you write to such a program's stdin through a pipe, and now wait for an answer from that program's stdout (without closing the ingress pipe), the answer is stuck in the stdio buffers and will never come out - This is a deadlock.
You can trick some line-oriented programs (eg grep) into not buffering by using a pseudo-tty to talk to them; take a look at libexpect(3). But in the general case, you would have to re-run a different subprocess for each message, allowing to use EOF to signal the end of each message and cause whatever buffers in the command (or pipeline of commands) to be flushed. Obviously not a good thing performance-wise.
See more info about this problem in the perlipc man page (it's for bi-directional pipes in Perl but the buffering considerations apply regardless of the language used for the main program).
You want something often called popen2. Here's a basic implementation without error checking (found by a web search, not my code):
// http://media.unpythonic.net/emergent-files/01108826729/popen2.c
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "popen2.h"
int popen2(const char *cmdline, struct popen2 *childinfo) {
pid_t p;
int pipe_stdin[2], pipe_stdout[2];
if(pipe(pipe_stdin)) return -1;
if(pipe(pipe_stdout)) return -1;
//printf("pipe_stdin[0] = %d, pipe_stdin[1] = %d\n", pipe_stdin[0], pipe_stdin[1]);
//printf("pipe_stdout[0] = %d, pipe_stdout[1] = %d\n", pipe_stdout[0], pipe_stdout[1]);
p = fork();
if(p < 0) return p; /* Fork failed */
if(p == 0) { /* child */
close(pipe_stdin[1]);
dup2(pipe_stdin[0], 0);
close(pipe_stdout[0]);
dup2(pipe_stdout[1], 1);
execl("/bin/sh", "sh", "-c", cmdline, NULL);
perror("execl"); exit(99);
}
childinfo->child_pid = p;
childinfo->to_child = pipe_stdin[1];
childinfo->from_child = pipe_stdout[0];
close(pipe_stdin[0]);
close(pipe_stdout[1]);
return 0;
}
//#define TESTING
#ifdef TESTING
int main(void) {
char buf[1000];
struct popen2 kid;
popen2("tr a-z A-Z", &kid);
write(kid.to_child, "testing\n", 8);
close(kid.to_child);
memset(buf, 0, 1000);
read(kid.from_child, buf, 1000);
printf("kill(%d, 0) -> %d\n", kid.child_pid, kill(kid.child_pid, 0));
printf("from child: %s", buf);
printf("waitpid() -> %d\n", waitpid(kid.child_pid, NULL, 0));
printf("kill(%d, 0) -> %d\n", kid.child_pid, kill(kid.child_pid, 0));
return 0;
}
#endif
popen() can only open the pipe in read or write mode, not both. Take a look at this thread for a workaround.
In one of netresolve backends I'm talking to a script and therefore I need to write to its stdin and read from its stdout. The following function executes a command with stdin and stdout redirected to a pipe. You can use it and adapt it to your liking.
static bool
start_subprocess(char *const command[], int *pid, int *infd, int *outfd)
{
int p1[2], p2[2];
if (!pid || !infd || !outfd)
return false;
if (pipe(p1) == -1)
goto err_pipe1;
if (pipe(p2) == -1)
goto err_pipe2;
if ((*pid = fork()) == -1)
goto err_fork;
if (*pid) {
/* Parent process. */
*infd = p1[1];
*outfd = p2[0];
close(p1[0]);
close(p2[1]);
return true;
} else {
/* Child process. */
dup2(p1[0], 0);
dup2(p2[1], 1);
close(p1[0]);
close(p1[1]);
close(p2[0]);
close(p2[1]);
execvp(*command, command);
/* Error occured. */
fprintf(stderr, "error running %s: %s", *command, strerror(errno));
abort();
}
err_fork:
close(p2[1]);
close(p2[0]);
err_pipe2:
close(p1[1]);
close(p1[0]);
err_pipe1:
return false;
}
https://github.com/crossdistro/netresolve/blob/master/backends/exec.c#L46
(I used the same code in Can popen() make bidirectional pipes like pipe() + fork()?)
Use forkpty (it's non-standard, but the API is very nice, and you can always drop in your own implementation if you don't have it) and exec the program you want to communicate with in the child process.
Alternatively, if tty semantics aren't to your liking, you could write something like forkpty but using two pipes, one for each direction of communication, or using socketpair to communicate with the external program over a unix socket.
You can't use popen to use two-way pipes.
In fact, some OSs don't support two-way pipes, in which case a socket-pair (socketpair) is the only way to do it.
popen works for me in both directions (read and write)
I have been using a popen() pipe in both directions..
Reading and writing a child process stdin and stdout with the file descriptor returned by popen(command,"w")
It seems to work fine..
I assumed it would work before I knew better, and it does.
According posts above this shouldn't work.. which worries me a little bit.
gcc on raspbian (raspbery pi debian)