[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: <close> and os.exit()
- From: Lorenzo Donati <lorenzodonatibz@...>
- Date: Sat, 30 May 2020 09:33:02 +0200
On 29/05/2020 22:57, Sean Conner wrote:
It was thus said that the Great Phil Leblanc once stated:
When os.exit() is called, by default the finalizer for <close>
variables is not executed. If the second (optional) argument to
os.exit() is true, then the Lua state is closed, and finalizers are
executed.
I didn't realize that!
local x <close>
...
os.exit(1) -- x finalizer is not called
os.exit(1, true) -- x finalizer is called
I suggest to change the default for the second exit() argument so that
the default be to call finalizers upon exit.
The reason for the behavior is to remain compatible with Lua 5.1. The
calls:
os.exit(1)
os.exit(1,nil)
os.exit(1,false)
are the same, because nil and false are "falsy values" in Lua (all else is
true). I can see the reasoning behind making the finalizers always called
on exit(), but it will result in different behavior between Lua 5.1 (which
is still widely used) and 5.2+.
Besides, I think using 'true' to signify NOT to do something is, to me,
counterintuitive.
-spc
I agree (reluctantly) on maintaining the backwards compatibility, but
<close> finalizers are different things. I would find rather unexpected
for them non being called on exit.
After all they have been introduced just to have deterministic RAII, so
calling them on exit by default (with no extra arg specifications) is
what probably is intended by most people.
Being inconsistent with GC finalizers probably is a little incoherent,
but only if you see the two as the same mechanism, which are not.
I already think it was wrong to decide that default behavior was NOT to
call GC finalizers on exit way back. I'd rather not repeat that error
with __close.
Moreover, as it stands, the manual could give a false impression, since
under 3.3.8 says:
"When calling the metamethod, the value itself is passed as the first
argument and the error object that caused the exit (if any) is passed as
a second argument;..."
"caused the exit" could well imply that os.exit causes __close to be
called. In any case the current behavior should be clarified here. After
all what is a "Lua state" is not obvious to people NOT using C API (i.e.
"pure" Lua programmers). Therefore, if current behavior is maintained a
little note here is on order (like: "But note that __close won't be
called by os.exit unless called with a true second argument")
And a similar annotation should be made on os.exit description, IMO.
And, please, note that while __gc might not be so relevant to a pure Lua
programmer (I guess it is used mainly with C API userdata, not with
Lua-side created tables -- correct me if I'm wrong), probably __close
will be, since it is the right tool to do RAII in Lua.
If one really wants NOT to call __close on exit, it would be better to
add another argument to exit (I know, ugly), or maybe define a new
behavior for exit when the second arg is a string, so that the string
specifies what to call or what not, e.g.:
os.exit( exit_code, 'noclose, nogc')
This would also match current behavior when called with an empty string
which is "true-y":
os.exit( exit, '' ) -- closes the state hence calls __gc and __close
BTW, could someone be interested in a behavior where __gc is NOT called
and __close is? Could be useful (I can't say, no much experience with __gc)?
In any case, I'd prefer a safer behavior at the cost of a bit of
"uncleanliness".
Or maybe just introduce a new function os.safeexit, that does the safest
thing, except when requested to do otherwise. And yes, I know you could
do that in your code easily, but these are basic functionalities and
behavior, they shouldn't be monkeypatched lightly.
It's quite confusing looking at other people's code when they change or
redefine basic functionalities, especially when they just want to make
their behavior saner.
Moreover, imagine the confusion when integrating different codebases,
which is not uncommon in Lua ecosystems, with all the different small
libraries out there.
If everyone had their own safeexit, with different signature and name, a
real hell!
As I hinted in my opening, I would rather prefer to break compatibility
than let exit NOT call __close by default. But again, the "everyone is
happy" approach would probably be introducing a os.safeexit function.
Cheers!
--Lorenzo Donati