Skip to content

Instantly share code, notes, and snippets.

@mhaberler
Created March 13, 2014 21:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mhaberler/9537478 to your computer and use it in GitHub Desktop.
Save mhaberler/9537478 to your computer and use it in GitHub Desktop.
integrate libreadline into a czmq event loop
// example for integrating readline and
// synchronous signal delivery with czmq/zloop
// Michael Haberler 3/2014
// gcc -g zreadline.o `pkg-config --cflags --libs libczmq` -lreadline -o zreadline
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <unistd.h>
#include <czmq.h>
#include <sys/signalfd.h>
int signo;
int eofseen = 0;
const char *prompt = "cmd> ";
static void my_rlhandler(char* line)
{
if (line == NULL) {
printf("EOF\n");
eofseen = 1;
} else {
if (strlen(line)) {
add_history(line);
}
printf("got line: '%s'\n", line);
free(line);
}
}
static int s_handle_input(zloop_t *loop, zmq_pollitem_t *poller, void *arg)
{
if (poller->revents & ZMQ_POLLIN)
rl_callback_read_char();
return 0;
}
static int s_handle_signal(zloop_t *loop, zmq_pollitem_t *poller, void *arg)
{
struct signalfd_siginfo fdsi;
ssize_t s = read(poller->fd, &fdsi, sizeof(struct signalfd_siginfo));
if (s != sizeof(struct signalfd_siginfo)) {
perror("read");
}
fprintf(stderr, "got signal %d '%s'\n",fdsi.ssi_signo,strsignal(fdsi.ssi_signo) );
signo = fdsi.ssi_signo;
return -1; // exit reactor
}
int main(int argc, char **argv)
{
int sfd, retval;
void *ctx = zctx_new();
assert(ctx);
zloop_t *loop = zloop_new();
assert (loop);
// suppress default handling of signals in zctx_new()
// since we're using signalfd()
zsys_handler_set(NULL);
sigset_t sigmask;
sigemptyset(&sigmask);
// block all signal delivery through default signal handlers
// since we're using signalfd()
sigfillset(&sigmask);
assert(sigprocmask(SIG_SETMASK, &sigmask, NULL) == 0);
// explicitly enable signals we want delivered via signalfd()
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGINT);
sigaddset(&sigmask, SIGQUIT);
sigaddset(&sigmask, SIGTERM);
sigaddset(&sigmask, SIGSEGV);
sigaddset(&sigmask, SIGFPE);
assert((sfd = signalfd(-1, &sigmask, 0)) >= 0);
zmq_pollitem_t signal_poller = { 0, sfd, ZMQ_POLLIN };
zloop_poller (loop, &signal_poller, s_handle_signal, NULL);
// readline setup
rl_callback_handler_install(prompt, (rl_vcpfunc_t*) &my_rlhandler);
zmq_pollitem_t input_poller = { 0, fileno(stdin), ZMQ_POLLIN };
zloop_poller (loop, &input_poller, s_handle_input, NULL);
do {
retval = zloop_start(loop);
} while (!retval && !eofseen);
rl_callback_handler_remove();
fprintf(stderr, "exiting, signal %d, retval %d, eofseen %d\n",
signo, retval, eofseen);
exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment