diff options
| author | William A. Kennington III <wak@google.com> | 2018-07-22 22:19:11 -0700 |
|---|---|---|
| committer | William A. Kennington III <wak@google.com> | 2018-07-23 10:47:36 -0700 |
| commit | 7b79fb551d70d7d5f326e1c1ffb6566f0b443a2b (patch) | |
| tree | 3f2b17e07d03405fd1e70d177fa59a1abcb199e3 | |
| parent | 86be5dd8a02c3abf685f6313213c9356b7b1708d (diff) | |
| download | sdeventplus-7b79fb551d70d7d5f326e1c1ffb6566f0b443a2b.tar.gz sdeventplus-7b79fb551d70d7d5f326e1c1ffb6566f0b443a2b.zip | |
example/follow: Implement
| -rw-r--r-- | example/follow.cpp | 110 |
1 files changed, 107 insertions, 3 deletions
diff --git a/example/follow.cpp b/example/follow.cpp index 36cd44b..7f72687 100644 --- a/example/follow.cpp +++ b/example/follow.cpp @@ -1,14 +1,118 @@ +#include <cerrno> #include <cstdio> +#include <cstring> +#include <exception> +#include <fcntl.h> +#include <functional> #include <sdeventplus/event.hpp> +#include <sdeventplus/source/event.hpp> +#include <sdeventplus/source/io.hpp> +#include <sdeventplus/source/signal.hpp> +#include <signal.h> +#include <sys/epoll.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +void reader(const char* fifo, sdeventplus::source::IO& source, int fd, uint32_t) +{ + char buf[4096]; + ssize_t r = read(fd, buf, sizeof(buf)); + if (r == 0) + { + int newfd = open(fifo, O_NONBLOCK | O_RDONLY); + if (newfd < 0) + { + fprintf(stderr, "Failed to open %s: %s\n", fifo, strerror(errno)); + source.get_event().exit(1); + return; + } + source.set_fd(newfd); + if (close(fd)) + { + fprintf(stderr, "Failed to close fd\n"); + source.get_event().exit(1); + return; + } + return; + } + if (r < 0) + { + fprintf(stderr, "Reader error: %s\n", strerror(errno)); + source.get_event().exit(1); + return; + } + printf("%.*s", static_cast<int>(r), buf); +} + +void remover(const char* fifo, sdeventplus::source::EventBase& source) +{ + int r = unlink(fifo); + if (r) + { + fprintf(stderr, "Failed to remove fifo %s: %s\n", fifo, + strerror(errno)); + source.get_event().exit(1); + } +} + +void clean_exit(sdeventplus::source::Signal& source, + const struct signalfd_siginfo*) +{ + source.get_event().exit(0); +} int main(int argc, char* argv[]) { if (argc != 2) { - fprintf(stderr, "Usage: %s [file]\n", argv[0]); + fprintf(stderr, "Usage: %s [named pipe to create]\n", argv[0]); return 1; } + const char* fifo = argv[1]; - sdeventplus::Event event = sdeventplus::Event::get_default(); - return event.loop(); + // Block all signals before changing system state so we guarantee our clean + // up routines are in place + sigset_t signals; + if (sigfillset(&signals)) + { + fprintf(stderr, "Failed to populate signals: %s\n", strerror(errno)); + return 1; + } + if (sigprocmask(SIG_BLOCK, &signals, nullptr)) + { + fprintf(stderr, "Failed to mask signals: %s\n", strerror(errno)); + return 1; + } + + if (mkfifo(fifo, 0622)) + { + fprintf(stderr, "Failed to mkfifo %s: %s\n", fifo, strerror(errno)); + return 1; + } + + int fd = open(fifo, O_NONBLOCK | O_RDONLY); + if (fd < 0) + { + fprintf(stderr, "Failed to open %s: %s\n", fifo, strerror(errno)); + return 1; + } + + try + { + sdeventplus::Event event = sdeventplus::Event::get_default(); + sdeventplus::source::Exit remover_source( + event, std::bind(remover, fifo, std::placeholders::_1)); + sdeventplus::source::Signal sigint(event, SIGINT, clean_exit); + sdeventplus::source::IO reader_source( + event, fd, EPOLLIN, + std::bind(reader, fifo, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3)); + return event.loop(); + } + catch (const std::exception& e) + { + fprintf(stderr, "%s\n", e.what()); + return 1; + } } |

