Skip to content
Snippets Groups Projects
Commit 384b92d1 authored by Florian Fischer's avatar Florian Fischer
Browse files

fsearch: keep track of stdout offset if needed

When stdout points to a file and not a pipe write atomicity is not
guarantied. Detect that stdout is a regular file and keep track
of its offset using a atomic offset variable in user space.
parent 167c3fce
No related branches found
No related tags found
No related merge requests found
Pipeline #77917 passed
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright © 2021-2022 Florian Fischer, Florian Schmaus
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <array>
#include <atomic>
#include <boost/program_options.hpp>
#include <climits>
#include <cstdlib>
......@@ -26,13 +28,30 @@ namespace po = boost::program_options;
#define EMPER_RIPGREP_BUFSIZE 4096
const char* needle;
size_t needle_len;
static const char* needle;
static size_t needle_len;
emper::Semaphore* max_running;
static emper::Semaphore* max_running;
static bool stdoutNeedsOffset = false;
static std::atomic<off_t> stdoutOffset = 0;
static enum emper::StealingMode stealingMode;
static void writeFoundPath(const std::string& path) {
std::array<char, PATH_MAX + 1> outBuf;
memcpy(outBuf.data(), path.c_str(), path.length());
outBuf[path.length()] = '\n';
const size_t outLen = path.length() + 1;
off_t offset = -1;
if (stdoutNeedsOffset)
offset = stdoutOffset.fetch_add(static_cast<off_t>(outLen), std::memory_order_relaxed);
emper::io::writeFileAndWait(STDOUT_FILENO, outBuf.data(), outLen, offset);
}
void search(const std::string& path) {
if (max_running) {
max_running->acquire();
......@@ -48,10 +67,7 @@ void search(const std::string& path) {
ssize_t bytes_read = emper::io::readFileAndWait(fd, buf.data(), buf.size(), 0);
while (bytes_read > 0) {
if (memmem(&buf[0], bytes_read, needle, needle_len)) {
std::array<char, PATH_MAX + 1> outBuf;
memcpy(outBuf.data(), path.c_str(), path.length());
outBuf[path.length()] = '\n';
emper::io::writeFileAndWait(STDOUT_FILENO, outBuf.data(), path.length() + 1, -1);
writeFoundPath(path);
goto out;
}
......@@ -105,6 +121,12 @@ static auto fssearch(const po::variables_map& vm) -> int {
Runtime runtime;
struct stat statBuf;
int res = fstat(STDOUT_FILENO, &statBuf);
if (res) DIE_MSG_ERRNO("fstat(STDOUT_FILENO) failed");
stdoutNeedsOffset = S_ISREG(statBuf.st_mode);
std::cerr << "Starting fsearch with stealingMode=" << stealingMode;
if (max_running) std::cerr << " and " << max_running->getCount() << " file fibers";
std::cerr << std::endl;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment