Overhaul the lthread_prints_ buffer.

This commit is contained in:
2026-02-09 17:03:22 -05:00
parent bf7cb9d258
commit 8fc4a3b94c
3 changed files with 69 additions and 79 deletions

View File

@@ -387,29 +387,24 @@ eng::string World::probe_lua_expr(int64_t actor_id, std::string_view lua) {
// Call the closure.
int top = lua_gettop(L);
lua_pushvalue(L, closure.index());
open_lthread_state(actor_id, actor_id, 0, false, true);
open_lthread_state(actor_id, actor_id, 0, false);
eng::string msg = traceback_pcall(L, 0, LUA_MULTRET);
// If there's an error message, print it.
// Otherwise, pretty-print the results.
std::ostream *ostream = lthread_print_stream();
if (msg.empty()) {
for (int i = top + 1; i <= lua_gettop(L); i++) {
LuaSpecial root(i);
pprint(LS, root, PrettyPrintOptions(), ostream);
pprint(LS, root, PrettyPrintOptions(), &lthread_prints_);
// TODO: this endl is unnecessary if we just printed a newline.
(*ostream) << std::endl;
lthread_prints_ << std::endl;
}
} else {
(*ostream) << msg << std::endl;
lthread_prints_ << msg << std::endl;
}
// Collect the lthread_prints (and also make sure they
// don't go into the printbuffer).
eng::string result = lthread_prints_->str();
lthread_prints_.reset();
close_lthread_state();
eng::string result = lthread_prints_.str();
clear_lthread_state();
return result;
}
@@ -478,15 +473,10 @@ void World::probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view
return;
}
open_lthread_state(actor_id, place_id, 0, false, true);
open_lthread_state(actor_id, place_id, 0, false);
eng::string msg = traceback_pcall(L, nargs, LUA_MULTRET);
LuaExtraArgs returnvalues(calltop + 1, lua_gettop(L) - calltop);
// Send any prints to the console.
eng::string prints = lthread_prints_->str();
lthread_prints_.reset();
util::dprint(prints);
// If a probe generates a lua error, we're not supposed to dprint it.
// Instead, we're supposed to send it back to unreal as the first
// return value of the function.
@@ -526,7 +516,7 @@ void World::probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view
}
}
close_lthread_state();
clear_lthread_state();
}
@@ -545,11 +535,10 @@ void World::probe_lua_call(int64_t actor_id, int64_t place_id, std::string_view
bool World::rebuild_sourcedb() {
bool ok = true;
for (const eng::string &mod: source_db_.modules()) {
open_lthread_state(0, 0, 0, false, true);
open_lthread_state(0, 0, 0, false);
eng::string err = source_db_.rebuild_module(mod);
eng::string prints = lthread_prints_->str();
lthread_prints_.reset();
close_lthread_state();
eng::string prints = lthread_prints_.str();
clear_lthread_state();
if (!err.empty()) ok = false;
if (!err.empty() || !prints.empty()) {
util::dprint("Loading Module ", mod);
@@ -705,9 +694,11 @@ HttpServerResponse World::http_serve(const HttpParser &request) {
int oldtop = lua_gettop(L);
lua_pushvalue(L, func.index());
lua_pushvalue(L, reqtab.index());
open_lthread_state(0, 0, 0, false, false);
open_lthread_state(0, 0, 0, false);
eng::string msg = traceback_pcall(L, 1, LUA_MULTRET);
close_lthread_state();
if (!msg.empty()) lthread_prints_ << msg << std::endl;
lthread_prints_to_dprint();
clear_lthread_state();
// If the call threw an error, return
// a 500 Internal Server Error to the client.
@@ -1073,10 +1064,9 @@ void World::run_scheduled_threads() {
// Resume the coroutine.
lua_State *CO = LS.ckthread(thread);
open_lthread_state(LS.ckinteger(actorid), sched.place_id(), sched.thread_id(), LS.ckboolean(useppool), true);
open_lthread_state(LS.ckinteger(actorid), sched.place_id(), sched.thread_id(), LS.ckboolean(useppool));
int nargs = LS.ckboolean(isnew) ? (lua_gettop(CO) - 1) : lua_gettop(CO);
int status = lua_resume(CO, nullptr, nargs);
std::ostream *ostream = lthread_print_stream();
if (status == LUA_OK) {
// Successfully ran to completion. Print any return values.
@@ -1086,8 +1076,8 @@ void World::run_scheduled_threads() {
LuaCoreStack LSCO(CO);
if (LS.ckboolean(print)) {
for (int i = 1; i <= lua_gettop(CO); i++) {
pprint(LSCO, LuaSpecial(i), PrettyPrintOptions(), ostream);
(*ostream) << std::endl;
pprint(LSCO, LuaSpecial(i), PrettyPrintOptions(), &lthread_prints_);
lthread_prints_ << std::endl;
}
}
} else if (status == LUA_YIELD) {
@@ -1106,11 +1096,12 @@ void World::run_scheduled_threads() {
// Currently, the error is sent to the actor. That seems... not right in the long run.
if (is_authoritative()) {
traceback_coroutine(CO);
(*ostream) << lua_tostring(CO, -1);
lthread_prints_ << lua_tostring(CO, -1);
}
LS.rawset(threads, sched.thread_id(), LuaNil);
}
close_lthread_state();
lthread_prints_to_printbuffer();
clear_lthread_state();
}
}
@@ -1140,14 +1131,15 @@ void World::clear_lthread_state() {
LS.rawset(globals, "actor", LuaNil);
LS.rawset(globals, "place", LuaNil);
lthread_prints_.reset();
lthread_actor_id_ = 0;
lthread_place_id_ = 0;
lthread_thread_id_ = 0;
lthread_use_ppool_ = false;
lthread_prints_.str();
lthread_prints_.clear();
}
void World::open_lthread_state(int64_t actor, int64_t place, int64_t thread, bool ppool, bool prints) {
void World::open_lthread_state(int64_t actor, int64_t place, int64_t thread, bool ppool) {
// Store actor and place in global variables.
LuaVar lactor, lplace, tangibles, globals;
LuaExtStack LS(state(), lactor, lplace, tangibles, globals);
@@ -1170,37 +1162,30 @@ void World::open_lthread_state(int64_t actor, int64_t place, int64_t thread, boo
lthread_place_id_ = place;
lthread_thread_id_ = thread;
lthread_use_ppool_ = ppool;
if (prints) {
lthread_prints_.reset(new eng::ostringstream);
} else {
lthread_prints_.reset();
}
lthread_prints_.str();
lthread_prints_.clear();
}
void World::close_lthread_state() {
// Copy prints from lthread_prints_ stringstream into
// the appropriate actor's PrintBuffer.
if (lthread_prints_ != nullptr) {
const eng::string &output = lthread_prints_->str();
if (output.size() > 0) {
Tangible *actor = tangible_get(lthread_actor_id_);
if (actor != nullptr) {
actor->print_buffer_.add_string(output, is_authoritative());
}
void World::lthread_prints_to_printbuffer()
{
const eng::string &output = lthread_prints_.str();
if (output.size() > 0) {
Tangible *actor = tangible_get(lthread_actor_id_);
if (actor != nullptr) {
actor->print_buffer_.add_string(output, is_authoritative());
}
}
// Now clean up everything.
clear_lthread_state();
}
std::ostream *World::lthread_print_stream() const {
if (lthread_prints_ != nullptr) {
return lthread_prints_.get();
} else {
return &std::cerr;
void World::lthread_prints_to_dprint()
{
const eng::string &output = lthread_prints_.str();
if (output.size() > 0) {
util::dprintview(output);
}
}
void World::set_global(const eng::string &gvar, std::string_view value) {
// Store the serialized blob.
//

View File

@@ -358,10 +358,12 @@ public:
// cleared.
//
void clear_lthread_state();
void open_lthread_state(int64_t actor_id, int64_t place_id, int64_t thread_id, bool ppool, bool prints);
void close_lthread_state();
void open_lthread_state(int64_t actor_id, int64_t place_id, int64_t thread_id, bool ppool);
std::ostream *lthread_print_stream() const;
std::ostream *lthread_print_stream() { return &lthread_prints_; }
void lthread_prints_to_printbuffer();
void lthread_prints_to_dprint();
// Set a lua global variable.
//
@@ -670,7 +672,7 @@ private:
int64_t lthread_place_id_;
int64_t lthread_thread_id_;
int64_t lthread_use_ppool_;
std::unique_ptr<eng::ostringstream> lthread_prints_;
eng::ostringstream lthread_prints_;
friend class Tangible;
friend int lfn_tangible_animate(lua_State *L);