On Sat, Jan 28, 2017 at 4:05 PM, T L <tapir....@gmail.com> wrote: > > > On Saturday, January 28, 2017 at 10:46:50 PM UTC+8, Dave Cheney wrote: >> >> >> >> On Sunday, 29 January 2017 01:42:08 UTC+11, T L wrote: >>> >>> >>> >>> On Saturday, January 28, 2017 at 10:33:08 PM UTC+8, Dave Cheney wrote: >>>> >>>> >>>> >>>> On Sunday, 29 January 2017 01:25:20 UTC+11, T L wrote: >>>>> >>>>> >>>>> >>>>> On Saturday, January 28, 2017 at 9:33:51 PM UTC+8, C Banning wrote: >>>>>> >>>>>> From the doc: "The finalizer for obj is scheduled to run at some >>>>>> arbitrary time after obj becomes unreachable. There is no guarantee that >>>>>> finalizers will run before a program exits, so typically they are useful >>>>>> only for releasing non-memory resources associated with an object during >>>>>> a >>>>>> long-running program." >>>>>> >>>>> >>>>> >>>>> If this is true, then the SetFinalizer function would be much >>>>> meaningless. >>>>> >>>> >>>> Yes. The only reasonable way to interpret the operation of SetFinalizer >>>> is to assume it does not thing and program accordingly. >>>> >>>> To repeat, you cannot base the correct operation of your program on a >>>> finaliser running before your program exits. >>>> >>> >>> I know, I just want to make sure some fanalizers will get executed for a >>> long running program. >>> >> >> Finalisers are not guaranteed to run, no matter how long the program runs >> for, no matter how important they are. >> >> >>> But it looks the current implementation of SetFinalizer can't make any >>> guarantee at all. >>> >> >> Correct. Finalisers are not guaranteed to run. You should not base the >> correct operation of your program on a finaliser running before your >> program exits. >> > > My understanding is finalisers are guaranteed to run for some cases, but > not for some other cases, for a long running program. >
Your understanding is false. They are not guaranteed to run, fullstop. > If any cases are not guaranteed to run, then SetFinalizer would be totally > useless. > See Konstantin's Post. They are not totally useless and their uses are documented (though I'd rephrase it as "resources that are not go-allocated memory"). You can not rely on them for correctness, but you *can* use them as an additional defense against some kind of bugs, like unclosed files. You can use them to do any kind of work that a) helps a long-running program not crash and b) is not necessary to do if your process dies. Examples are * freeing C-allocated memory (the OS will cleanup after you, but a long-running program will crash, if it accidentally doesn't free the memory manually) * Closing files (the OS will automatically close all files when your process exits, but a long-running program might run out of FDs and crash if it accidentally doesn't close the files) * Munmap a memory region (the OS will unmap the files anyway when you exit, but…) In all of these cases, your program doesn't *rely* on the Finalizer to run, for correctness, but it will be helped by it, in the presence of bugs. But a Finalizer is not a Destructor and that's also a *good* thing. Consider C++, where most of the work of Destructors is 100% unnecessary when the process exits, but is still done; now your program exiting/restarting is unnecessarily slowed down by doing work that the kernel can do more efficiently for you. > > BTW, more study: > > package main > > import "time" > import "runtime" > > type E int8 > const N=2 > > type T [N]E > > func main() { > for i := range [8]struct{}{} { > t := &T{0:E(i)} > runtime.SetFinalizer(t, func(p *T) {print((*p)[0])}) > } > runtime.GC() > time.Sleep(time.Second * 1) > } > > output: > .......E..........output(N=1)..........output(N=2) > .......int8....... ....................7654 > .......int16......7654.................765432 > .......int32......765432...............7654321 > .......int64......7654321..............76543210 > > > > >> >>> >>> >>>> >>>>> BTW, it looks both finalizer will get executed if let the program >>>>> sleep more than 10us at the beginning: >>>>> >>>>> package main >>>>> >>>>> import "time" >>>>> import "runtime" >>>>> >>>>> func main() { >>>>> time.Sleep(10 * time.Microsecond) >>>>> // if sleep 10 Microsecond here, 2 and 1 will both be out >>>>> // if sleep 1 Microsecond here, still only 2 will out >>>>> >>>>> t1 := new(int) >>>>> t2 := new(int) >>>>> >>>>> runtime.SetFinalizer(t1, func(*int) {println(1)}) >>>>> runtime.SetFinalizer(t2, func(*int) {println(2)}) >>>>> runtime.GC() >>>>> time.Sleep(time.Second * 20) >>>>> } >>>>> >>>>> >>>>>> >>>>>> >>>>>> On Saturday, January 28, 2017 at 6:17:37 AM UTC-7, T L wrote: >>>>>>> >>>>>>> >>>>>>> >>>>>>> package main >>>>>>> >>>>>>> import "time" >>>>>>> import "runtime" >>>>>>> >>>>>>> type T1 struct{ i int } >>>>>>> type T2 struct{ i int } >>>>>>> >>>>>>> func main() { >>>>>>> t1 := new(T1) >>>>>>> t2 := new(T2) >>>>>>> >>>>>>> runtime.SetFinalizer(t1, func(*T1) {println(1)}) >>>>>>> runtime.SetFinalizer(t2, func(*T2) {println(2)}) >>>>>>> runtime.GC() >>>>>>> time.Sleep(time.Second * 2) >>>>>>> >>>>>>> // the program will output: 2 >>>>>>> // if I adjust the order of the declarations of t1 and t2, >>>>>>> // the program will output: 1 >>>>>>> } >>>>>>> >>>>>>> Why the finalizer for the first declaration will not get called? >>>>>>> >>>>>> -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.