lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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