|
|
|
@@ -18,7 +18,7 @@ const char* UCE_CLI_SYMBOL = "__uce_cli";
|
|
|
|
|
const char* UCE_SERVE_HTTP_SYMBOL = "__uce_serve_http";
|
|
|
|
|
const char* UCE_ONCE_SYMBOL = "__uce_once";
|
|
|
|
|
const char* UCE_INIT_SYMBOL = "__uce_init";
|
|
|
|
|
const u64 UCE_UNIT_ABI_VERSION = 4;
|
|
|
|
|
const u64 UCE_UNIT_ABI_VERSION = 5;
|
|
|
|
|
|
|
|
|
|
struct SharedUnitFilesystemState
|
|
|
|
|
{
|
|
|
|
@@ -995,6 +995,15 @@ SharedUnit* compiler_load_shared_unit(Request* context, String file_name, String
|
|
|
|
|
printf("%s\n", display_messages.c_str());
|
|
|
|
|
if(compiler_can_write_response(context) && context->stats.invoke_count == 1)
|
|
|
|
|
{
|
|
|
|
|
DTree error_info;
|
|
|
|
|
error_info["type"] = "compiler_error";
|
|
|
|
|
error_info["status"] = su->compile_status;
|
|
|
|
|
error_info["source"] = su->file_name;
|
|
|
|
|
error_info["compiler_output"] = su->compiler_messages;
|
|
|
|
|
error_info["generated_cpp"] = compiler_generated_cpp_path(su);
|
|
|
|
|
error_info["details"] = display_messages;
|
|
|
|
|
if(compiler_render_error_page(context, "page_compiler_error", 500, "UCE Unit Compile Error", error_info))
|
|
|
|
|
return(0);
|
|
|
|
|
context->set_status(500, "UCE Unit Compile Error");
|
|
|
|
|
context->header["Content-Type"] = "text/plain; charset=utf-8";
|
|
|
|
|
}
|
|
|
|
@@ -1739,9 +1748,106 @@ bool compiler_invoke_component(Request* context, String file_name, String render
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String compiler_error_page_unit(Request* context, String config_key)
|
|
|
|
|
{
|
|
|
|
|
if(!context || !context->server)
|
|
|
|
|
return("");
|
|
|
|
|
String configured = trim(first(
|
|
|
|
|
context->server->config[config_key],
|
|
|
|
|
context->server->config[to_upper(config_key)]
|
|
|
|
|
));
|
|
|
|
|
if(configured == "")
|
|
|
|
|
return("");
|
|
|
|
|
// Resolve relative to where the server was started, not the volatile
|
|
|
|
|
// per-unit working directory (which is also stale right after a fault).
|
|
|
|
|
String resolved = compiler_resolve_unit_path(context, configured, process_start_directory());
|
|
|
|
|
if(resolved == "" || !file_exists(resolved))
|
|
|
|
|
return("");
|
|
|
|
|
return(resolved);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool compiler_render_error_page(Request* context, String config_key, s32 status_code, String status_reason, DTree error_info)
|
|
|
|
|
{
|
|
|
|
|
if(!compiler_can_write_response(context))
|
|
|
|
|
return(false);
|
|
|
|
|
if(!context->server || context->resources.error_page_active)
|
|
|
|
|
return(false);
|
|
|
|
|
String unit_file = compiler_error_page_unit(context, config_key);
|
|
|
|
|
if(unit_file == "")
|
|
|
|
|
return(false);
|
|
|
|
|
|
|
|
|
|
String previous_response_code = context->response_code;
|
|
|
|
|
s32 previous_status = context->flags.status;
|
|
|
|
|
String previous_content_type = context->header["Content-Type"];
|
|
|
|
|
|
|
|
|
|
context->resources.error_page_active = true;
|
|
|
|
|
context->call["error"] = error_info;
|
|
|
|
|
context->set_status(status_code, status_reason);
|
|
|
|
|
context->header["Content-Type"] = first(context->server->config["CONTENT_TYPE"], "text/html; charset=utf-8");
|
|
|
|
|
|
|
|
|
|
ob_start();
|
|
|
|
|
String error_message = "";
|
|
|
|
|
bool rendered = compiler_invoke_render(context, unit_file, "render", &error_message);
|
|
|
|
|
String html = ob_get_close();
|
|
|
|
|
context->resources.error_page_active = false;
|
|
|
|
|
|
|
|
|
|
if(!rendered)
|
|
|
|
|
{
|
|
|
|
|
printf("(!) configured %s page %s failed to render: %s\n", config_key.c_str(), unit_file.c_str(), trim(error_message).c_str());
|
|
|
|
|
context->response_code = previous_response_code;
|
|
|
|
|
context->flags.status = previous_status;
|
|
|
|
|
context->header["Content-Type"] = previous_content_type;
|
|
|
|
|
context->call.remove("error");
|
|
|
|
|
return(false);
|
|
|
|
|
}
|
|
|
|
|
print(html);
|
|
|
|
|
return(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool compiler_unit_compile_pending(Request* context, String file_name)
|
|
|
|
|
{
|
|
|
|
|
String normalized = compiler_normalize_unit_path(context, file_name);
|
|
|
|
|
if(normalized == "" || !file_exists(normalized))
|
|
|
|
|
return(false);
|
|
|
|
|
if(compiler_reusable_cached_unit(context, normalized, false, false))
|
|
|
|
|
return(false);
|
|
|
|
|
|
|
|
|
|
SharedUnit probe;
|
|
|
|
|
setup_unit_paths(context, &probe, normalized);
|
|
|
|
|
auto state = inspect_shared_unit_filesystem(context, &probe);
|
|
|
|
|
if(!shared_unit_compile_check(state).needs_compile)
|
|
|
|
|
return(false);
|
|
|
|
|
// A persisted, still-current failure is a compiler error, not a build in
|
|
|
|
|
// progress: let the load path surface it.
|
|
|
|
|
if(compiler_failure_retry_deferred(context, &probe, state))
|
|
|
|
|
return(false);
|
|
|
|
|
return(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compiler_invoke(Request* context, String file_name)
|
|
|
|
|
{
|
|
|
|
|
printf("(i) compiler_invoke file %s\n", file_name.c_str());
|
|
|
|
|
|
|
|
|
|
// Entry-unit hook for the configured "compiling" page: when the unit needs
|
|
|
|
|
// a (re)build that the proactive compiler can deliver, answer immediately
|
|
|
|
|
// instead of blocking the worker on a synchronous compile.
|
|
|
|
|
if(context && context->stats.invoke_count == 0 &&
|
|
|
|
|
!context->resources.is_cli && !context->resources.error_page_active &&
|
|
|
|
|
config_bool("PROACTIVE_COMPILE_ENABLED", true) &&
|
|
|
|
|
compiler_error_page_unit(context, "page_compiling") != "")
|
|
|
|
|
{
|
|
|
|
|
String resolved = compiler_resolve_unit_path(context, file_name, "");
|
|
|
|
|
if(resolved != "" && compiler_unit_compile_pending(context, resolved))
|
|
|
|
|
{
|
|
|
|
|
compiler_track_known_unit(context, resolved);
|
|
|
|
|
DTree error_info;
|
|
|
|
|
error_info["type"] = "compiling";
|
|
|
|
|
error_info["source"] = resolved;
|
|
|
|
|
if(compiler_render_error_page(context, "page_compiling", 503, "UCE Unit Compiling", error_info))
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String error_message = "";
|
|
|
|
|
if(!compiler_invoke_render(context, file_name, "render", &error_message) && error_message != "")
|
|
|
|
|
{
|
|
|
|
|