otland / forgottenserver

A free and open-source MMORPG server emulator written in C++
https://otland.net
GNU General Public License v2.0
1.59k stars 1.06k forks source link

lua "print" gets stuck until std::cout is called (linux terminal / git bash) #4045

Closed Zbizu closed 4 months ago

Zbizu commented 2 years ago

Summary

Lua print output is not visible (windows git bash / linux terminal) until c++ output (eg. std::cout) updates the console this might be useful: https://stackoverflow.com/questions/15787892/embedded-lua-does-not-print-to-allocated-console

Steps to reproduce

  1. compile
  2. run in linux terminal or windows git bash
  3. print from lua
  4. check console
  5. log in/out

Expected behaviour

print output shows instantly like in cmd and powershell

Actual behaviour

print output is not visible until non-lua output (eg. std::cout) is called

Environment

I got this problem in git bash, but another user in discord mentioned that he's facing that issue in linux also

Reproduction environment

I managed to reproduce it on master branch at commit 4038

example script (!test):

local talk = TalkAction("!test")
local t = {}

function talk.onSay(player, words, param)
    t[#t + 1] = #t
    print(#t)
    return false
end

talk:register()
Zbizu commented 2 years ago

update: A potential fix could be changing stdout to a custom stream the way it would trigger std::cout from within luascript.cpp to ensure proper execution, unfortunately I don't know how to modify _G.io.stdout from within the sources

here are the sources of various Lua io libs if it helps: https://www.lua.org/source/5.1/liolib.c.html https://www.lua.org/source/5.2/liolib.c.html https://github.com/LuaJIT/LuaJIT/blob/v2.1/src/lib_io.c

Zbizu commented 2 years ago

update: std::flush seems to be updating the terminal when it gets stuck. I still don't know how to attach it to print/io.write

Zbizu commented 2 years ago

update: https://github.com/Zbizu/forgottenserver/commit/3dbc562ddf99953232726c695be43fb7e651c5c9 this seems to do the trick, though I'm not sure whether using an ugly workaround (adding code around default Lua functions) is the best solution or if calling std::flush constantly doesn't have some unknown consequences.

files to look at:

amatria commented 2 years ago

This is the expected behaviour of any buffered I/O stream such as stdout... Use io.flush() next time

Also, overriding the default print function to call std::flush is going to affect performance indeed. I/O times are not deterministic, and so waiting for the stream buffer to be flushed may incur big overheads. Needless to say, overriding the default print function to call a host C++ function will also affect performance in the long run...

nekiro commented 4 months ago

As @amatria mentioned, this is how i/o works, it's not flushed right away, but buffered in some cases to enhance performance, flushing is pretty costly operation.

I'm closing this as there is nothing to fix.