Skip to content

Commit

Permalink
nixd/Server: split worker in a dedicated class (#230)
Browse files Browse the repository at this point in the history
This should fix some async-signal unsafe calls (causing the forked
process hangs).
  • Loading branch information
inclyc authored Jul 27, 2023
2 parents c080d75 + e07e862 commit 00d67dc
Show file tree
Hide file tree
Showing 27 changed files with 808 additions and 629 deletions.
4 changes: 4 additions & 0 deletions lspserver/include/lspserver/DraftStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ class DraftStore {

llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> asVFS() const;

/// LSP defines file versions as numbers that increase.
/// treats them as opaque and therefore uses strings instead.
static std::string encodeVersion(std::optional<int64_t> LSPVersion);

static std::optional<int64_t> decodeVersion(llvm::StringRef Encoded);

private:
Expand Down
3 changes: 0 additions & 3 deletions lspserver/include/lspserver/LSPServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@

#include <memory>

#include <llvm/ADT/StringRef.h>
#include <llvm/Support/JSON.h>

namespace lspserver {

/// LSPServer wraps inputs & outputs, associate message IDs between calls/reply,
Expand Down
4 changes: 4 additions & 0 deletions lspserver/src/DraftStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ static void updateVersion(DraftStore::Draft &D,
}
}

std::string DraftStore::encodeVersion(std::optional<int64_t> LSPVersion) {
return LSPVersion ? std::to_string(*LSPVersion) : "";
}

std::string DraftStore::addDraft(PathRef File, llvm::StringRef Version,
llvm::StringRef Contents) {
std::lock_guard<std::mutex> Lock(Mutex);
Expand Down
22 changes: 22 additions & 0 deletions nixd/include/nixd/Nix/Eval.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <nix/eval-inline.hh>
#include <nix/shared.hh>

namespace nix {

// Copy-paste from nix source code, do not know why it is inlined.

inline void EvalState::evalAttrs(Env &env, Expr *e, Value &v, const PosIdx pos,
std::string_view errorCtx) {
try {
e->eval(*this, env, v);
if (v.type() != nAttrs)
error("value is %1% while a set was expected", showType(v))
.withFrame(env, *e)
.debugThrow<TypeError>();
} catch (Error &e) {
e.addTrace(positions[pos], errorCtx);
throw;
}
}

} // namespace nix
16 changes: 16 additions & 0 deletions nixd/include/nixd/Nix/Init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <nix/eval.hh>
#include <nix/globals.hh>
#include <nix/shared.hh>

namespace nixd {

inline void initEval() {
nix::initNix();
nix::initLibStore();
nix::initPlugins();
nix::initGC();
}

} // namespace nixd
52 changes: 52 additions & 0 deletions nixd/include/nixd/Server/Config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

#include <list>
#include <string>
#include <thread>
#include <vector>

namespace nixd::configuration {

inline std::list<std::string> toNixArgs(const std::vector<std::string> &Args) {
return {Args.begin(), Args.end()};
}
struct InstallableConfigurationItem {
std::vector<std::string> args;
std::string installable;

[[nodiscard]] bool empty() const {
return args.empty() && installable.empty();
}

[[nodiscard]] auto nArgs() const { return toNixArgs(args); }
};

struct TopLevel {

struct Eval {
/// Nix installables that will be used for root translation unit.
InstallableConfigurationItem target;

/// The depth you'd like to eval *after* reached "installable" target.
int depth = 0;
/// Number of workers forking
/// defaults to std::thread::hardware_concurrency
int workers = static_cast<int>(std::thread::hardware_concurrency());
};

Eval eval;

struct Formatting {
std::string command = "nixpkgs-fmt";
};
Formatting formatting;

struct Options {
bool enable = false;
InstallableConfigurationItem target;
};

Options options;
};

} // namespace nixd::configuration
31 changes: 31 additions & 0 deletions nixd/include/nixd/Server/ConfigSerialization.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include "Config.h"

#include <llvm/Support/JSON.h>

namespace nixd::configuration {

llvm::json::Value toJSON(const TopLevel::Eval &R);

llvm::json::Value toJSON(const TopLevel::Formatting &R);

llvm::json::Value toJSON(const TopLevel::Options &R);

llvm::json::Value toJSON(const InstallableConfigurationItem &R);

bool fromJSON(const llvm::json::Value &Params, TopLevel::Eval &R,
llvm::json::Path P);

bool fromJSON(const llvm::json::Value &Params, TopLevel::Formatting &R,
llvm::json::Path P);

bool fromJSON(const llvm::json::Value &Params, TopLevel::Options &R,
llvm::json::Path P);

bool fromJSON(const llvm::json::Value &Params, TopLevel &R, llvm::json::Path P);

bool fromJSON(const llvm::json::Value &Params, InstallableConfigurationItem &R,
llvm::json::Path P);

} // namespace nixd::configuration
Loading

0 comments on commit 00d67dc

Please sign in to comment.