#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
-
+#include "common/errno.h"
#if defined(_AIX)
extern char *sys_siglist[];
#endif
#include "common/Thread.h"
#include <errno.h>
+void get_name_by_pid(pid_t pid, char *task_name)
+{
+ char proc_pid_path[PATH_MAX] = {0};
+ snprintf(proc_pid_path, PATH_MAX, "/proc/%d/cmdline", pid);
+ int fd = open(proc_pid_path, O_RDONLY);
+
+ if (fd < 0) {
+ fd = -errno;
+ derr << "Fail to open '" << proc_pid_path
+ << "' error = " << cpp_strerror(fd)
+ << dendl;
+ return;
+ }
+
+ int ret = read(fd, task_name, PATH_MAX-1);
+ if (ret < 0) {
+ ret = -errno;
+ derr << "Fail to read '" << proc_pid_path
+ << "' error = " << cpp_strerror(ret)
+ << dendl;
+ }
+
+ close(fd);
+}
+
+
/**
* safe async signal handler / dispatcher
*
/// for an individual signal
struct safe_handler {
+
+ safe_handler() {
+ memset(pipefd, 0, sizeof(pipefd));
+ memset(&handler, 0, sizeof(handler));
+ memset(&info_t, 0, sizeof(info_t));
+ }
+
+ siginfo_t info_t;
int pipefd[2]; // write to [1], read from [0]
signal_handler_t handler;
};
if (handlers[signum]) {
r = read(handlers[signum]->pipefd[0], &v, 1);
if (r == 1) {
+ char task_name[PATH_MAX] = "unknown";
+ siginfo_t * siginfo = &handlers[signum]->info_t;
+ get_name_by_pid(siginfo->si_pid, task_name);
+ derr << "received signal: " << sys_siglist[signum]
+ << " from " << " PID: " << siginfo->si_pid
+ << " task name: " << task_name
+ << " UID: " << siginfo->si_uid
+ << dendl;
handlers[signum]->handler(signum);
}
}
}
lock.Unlock();
- } else {
- //cout << "no data, got r=" << r << " errno=" << errno << std::endl;
- }
+ }
}
return NULL;
}
assert(r == 1);
}
+ void queue_signal_info(int signum, siginfo_t *siginfo, void * content) {
+ // If this signal handler is registered, the callback must be
+ // defined. We can do this without the lock because we will never
+ // have the signal handler defined without the handlers entry also
+ // being filled in.
+ assert(handlers[signum]);
+ memcpy(&handlers[signum]->info_t, siginfo, sizeof(siginfo_t));
+ int r = write(handlers[signum]->pipefd[1], " ", 1);
+ assert(r == 1);
+ }
+
void register_handler(int signum, signal_handler_t handler, bool oneshot);
void unregister_handler(int signum, signal_handler_t handler);
};
static SignalHandler *g_signal_handler = NULL;
-static void handler_hook(int signum)
-{
- g_signal_handler->queue_signal(signum);
+static void handler_signal_hook(int signum, siginfo_t * siginfo, void * content) {
+ g_signal_handler->queue_signal_info(signum, siginfo, content);
}
void SignalHandler::register_handler(int signum, signal_handler_t handler, bool oneshot)
struct sigaction act;
memset(&act, 0, sizeof(act));
- act.sa_handler = handler_hook;
+ act.sa_handler = (signal_handler_t)handler_signal_hook;
sigfillset(&act.sa_mask); // mask all signals in the handler
- act.sa_flags = oneshot ? SA_RESETHAND : 0;
-
+ act.sa_flags = SA_SIGINFO | (oneshot ? SA_RESETHAND : 0);
int ret = sigaction(signum, &act, &oldact);
assert(ret == 0);
}