Skip to content

Commit

Permalink
bootstrap: handle snapshot errors gracefully
Browse files Browse the repository at this point in the history
This patch refactors the SnapshotBuilder::Generate() routines
so that when running into errors during the snapshot building
process, they can exit gracefully by printing the error
and return a non-zero exit code. If the error is likely to
be caused by internal scripts, the return code would be 12,
if the error is caused by user scripts the return code would
be 1. In addition this refactors the generation of embedded
snapshots and directly writes to the output file stream
instead of producing an intermediate string with string
streams.

PR-URL: #43531
Refs: #35711
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
  • Loading branch information
joyeecheung committed Jul 15, 2022
1 parent 9bfabe8 commit 49bb1c6
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 172 deletions.
3 changes: 3 additions & 0 deletions doc/api/process.md
Expand Up @@ -3822,6 +3822,9 @@ cases:
options were set, but the port number chosen was invalid or unavailable.
* `13` **Unfinished Top-Level Await**: `await` was used outside of a function
in the top-level code, but the passed `Promise` never resolved.
* `14` **Snapshot Failure**: Node.js was started to build a V8 startup
snapshot and it failed because certain requirements of the state of
the application were not met.
* `>128` **Signal Exits**: If Node.js receives a fatal signal such as
`SIGKILL` or `SIGHUP`, then its exit code will be `128` plus the
value of the signal code. This is a standard POSIX practice, since
Expand Down
19 changes: 16 additions & 3 deletions src/env.h
Expand Up @@ -963,13 +963,17 @@ struct EnvSerializeInfo {
};

struct SnapshotData {
// The result of v8::SnapshotCreator::CreateBlob() during the snapshot
// building process.
v8::StartupData v8_snapshot_blob_data;
enum class DataOwnership { kOwned, kNotOwned };

static const size_t kNodeBaseContextIndex = 0;
static const size_t kNodeMainContextIndex = kNodeBaseContextIndex + 1;

DataOwnership data_ownership = DataOwnership::kOwned;

// The result of v8::SnapshotCreator::CreateBlob() during the snapshot
// building process.
v8::StartupData v8_snapshot_blob_data{nullptr, 0};

std::vector<size_t> isolate_data_indices;
// TODO(joyeecheung): there should be a vector of env_info once we snapshot
// the worker environments.
Expand All @@ -979,6 +983,15 @@ struct SnapshotData {
// read only space. We use native_module::CodeCacheInfo because
// v8::ScriptCompiler::CachedData is not copyable.
std::vector<native_module::CodeCacheInfo> code_cache;

~SnapshotData();

SnapshotData(const SnapshotData&) = delete;
SnapshotData& operator=(const SnapshotData&) = delete;
SnapshotData(SnapshotData&&) = delete;
SnapshotData& operator=(SnapshotData&&) = delete;

SnapshotData() = default;
};

class Environment : public MemoryRetainer {
Expand Down
11 changes: 6 additions & 5 deletions src/node_snapshot_builder.h
Expand Up @@ -15,13 +15,14 @@ struct SnapshotData;

class NODE_EXTERN_PRIVATE SnapshotBuilder {
public:
static std::string Generate(const std::vector<std::string> args,
const std::vector<std::string> exec_args);
static int Generate(std::ostream& out,
const std::vector<std::string> args,
const std::vector<std::string> exec_args);

// Generate the snapshot into out.
static void Generate(SnapshotData* out,
const std::vector<std::string> args,
const std::vector<std::string> exec_args);
static int Generate(SnapshotData* out,
const std::vector<std::string> args,
const std::vector<std::string> exec_args);

// If nullptr is returned, the binary is not built with embedded
// snapshot.
Expand Down

0 comments on commit 49bb1c6

Please sign in to comment.