Skip to content

Instantly share code, notes, and snippets.

@tetsu-koba
Last active April 26, 2024 04:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tetsu-koba/4e8674b9fd89281b480b9a81ee06fa52 to your computer and use it in GitHub Desktop.
Save tetsu-koba/4e8674b9fd89281b480b9a81ee06fa52 to your computer and use it in GitHub Desktop.
const std = @import("std");
const os = std.os;
const log = std.log;
const time = std.time;
const MAX_EVENT = 5;
const READ_BUFSIZE = 64 * 1024;
const WRITE_BUFSIZE = 64 * 1024;
fn createSignalfd() !os.fd_t {
var mask = os.empty_sigset;
os.linux.sigaddset(&mask, os.linux.SIG.INT);
os.linux.sigaddset(&mask, os.linux.SIG.TERM);
os.linux.sigaddset(&mask, os.linux.SIG.USR1);
os.linux.sigaddset(&mask, os.linux.SIG.USR2);
os.sigprocmask(os.linux.SIG.BLOCK, &mask, null);
return try os.signalfd(-1, &mask, os.linux.SFD.CLOEXEC);
}
fn writeFull(fd: os.fd_t, buf: []u8) os.WriteError!void {
var written: usize = 0;
var n: usize = 0;
while (written < buf.len) {
n = try os.write(fd, buf[written..]);
written += n;
}
}
const filter_op = *const fn (rbuf: []u8, wbuf: []u8) usize;
fn filterLoop(f: filter_op, timeout: i32, verbose0: bool) !void {
var verbose = verbose0;
var running = true;
var read_buffer: [READ_BUFSIZE]u8 = .{};
var write_buffer: [WRITE_BUFSIZE]u8 = .{};
const epoll_fd = try os.epoll_create1(os.linux.EPOLL.CLOEXEC);
defer os.close(epoll_fd);
var read_event = os.linux.epoll_event{
.events = os.linux.EPOLL.IN,
.data = os.linux.epoll_data{ .fd = os.linux.STDIN_FILENO },
};
try os.epoll_ctl(epoll_fd, os.linux.EPOLL.CTL_ADD, read_event.data.fd, &read_event);
const signal_fd = try createSignalfd();
defer os.close(signal_fd);
var signal_event = os.linux.epoll_event{
.events = os.linux.EPOLL.IN,
.data = os.linux.epoll_data{ .fd = signal_fd },
};
try os.epoll_ctl(epoll_fd, os.linux.EPOLL.CTL_ADD, signal_event.data.fd, &signal_event);
while (running) {
var events: [MAX_EVENT]os.linux.epoll_event = .{};
const event_count = os.epoll_wait(epoll_fd, events[0..], timeout);
if (event_count == 0) {
log.info("{d}:timeout", .{time.milliTimestamp()});
continue;
}
for (events[0..event_count]) |ev| {
if (ev.data.fd == read_event.data.fd) {
const bytes_read = try os.read(ev.data.fd, read_buffer[0..]);
if (verbose) {
log.info("{d}:bytes_read={d}", .{ time.milliTimestamp(), bytes_read });
}
if (bytes_read == 0) {
running = false;
} else {
const n = f(read_buffer[0..bytes_read], write_buffer[0..]);
if (n < 0) {
running = false;
}
try writeFull(os.linux.STDOUT_FILENO, write_buffer[0..n]);
}
} else if (ev.data.fd == signal_event.data.fd) {
var buf: [@sizeOf(os.linux.signalfd_siginfo)]u8 align(8) = undefined;
if (buf.len != try os.read(signal_event.data.fd, &buf)) {
return os.ReadError.ReadError;
}
const info = @ptrCast(*os.linux.signalfd_siginfo, &buf);
switch (info.signo) {
os.linux.SIG.INT => {
log.info("{d}:Got SIGINT", .{time.milliTimestamp()});
running = false;
},
os.linux.SIG.TERM => {
log.info("{d}:Got SIGTERM", .{time.milliTimestamp()});
running = false;
},
os.linux.SIG.USR1 => {
log.info("{d}:Set verbose=false", .{time.milliTimestamp()});
verbose = false;
},
os.linux.SIG.USR2 => {
log.info("{d}:Set verbose=true", .{time.milliTimestamp()});
verbose = true;
},
else => unreachable,
}
} else {
unreachable;
}
}
}
}
fn nopFilter(rbuf: []u8, wbuf: []u8) usize {
// Just copy now, replace this to do something great
@memcpy(wbuf, rbuf);
return rbuf.len;
}
pub fn main() !void {
// TODO: get parameters from command line options
const timeout = 10 * 1000;
const verbose = true;
try filterLoop(nopFilter, timeout, verbose);
}
@nevakrien
Copy link

does not compile...

(base) user@user-System-Product-Name:/Desktop/redis_stuff/realtimeDB$ zig build-exe epoll.zig
epoll.zig:80:30: error: expected 1 argument, found 2
const info = @ptrCast(*os.linux.signalfd_siginfo, &buf);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(base) user@user-System-Product-Name:
/Desktop/redis_stuff/realtimeDB$

@tetsu-koba
Copy link
Author

Help yourself. This sample program was written at the age of zig 0.10.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment