Why finalizer is never called? - go

var p = &sync.Pool{
New: func() interface{} {
return &serveconn{}
},
}
func newServeConn() *serveconn {
sc := p.Get().(*serveconn)
runtime.SetFinalizer(sc, (*serveconn).finalize)
fmt.Println(sc, "SetFinalizer")
return sc
}
func (sc *serveconn) finalize() {
fmt.Println(sc, "finalize")
*sc = serveconn{}
runtime.SetFinalizer(sc, nil)
p.Put(sc)
}
The above code tries to reuse object by SetFinalizer, but after debug I found finalizer is never called, why?
UPDATE
This may be related:https://github.com/golang/go/issues/2368

The above code tries to reuse object by SetFinalizer, but after debug I found finalizer is never called, why?
The finalizer is only called on an object when the GC
marks it as unused and then tries to sweep (free) at the end
of the GC cycle.
As a corollary, if a GC cycle is never performed during the runtime of your program, the finalizers you set may never be called.
Just in case you might hold a wrong assumption about the Go's GC, it may worth noting that Go does not employ reference counting on values; instead, it uses GC which works in parallel with the program, and the sessions during which it works happen periodically and are triggered by certain parameters like pressure on the heap produced by allocations.
A couple assorted notes regarding finalizers:
When the program terminates, no GC is forcibly run.
A corollary of this is that a finalizer is not guaranteed
to run at all.
If the GC finds a finalizer on an object about to be freed,
it calls the finalizer but does not free the object.
The object itself will be freed only at the next GC cycle —
wasting the memory.
All in all, you appear as trying to implement destructors.
Please don't: make your objects implement the sort-of standard method called Close and state in the contract of your type that the programmer is required to call it when they're done with the object.
When a programmer wants to call such a method no matter what, they use defer.
Note that this approach works perfectly for all types in the Go
stdlib which wrap resources provided by the OS—file and socket descriptors. So there is no need to pretend your types are somehow different.
Another useful thing to keep in mind is that Go was explicitly engineered to be no-nonsense, no-frills, no-magic, in-your-face language, and you're just trying to add magic to it.
Please don't, those who like decyphering layers of magic do program in Scala different languages.

Related

Close() invocations and the garbage collector

In Go, interfaces that use resources like network connections usually have a Close() method that disposes of these resources.
Now I wonder what would happen if the associated structs implementing the interface get garbage-collected without Close having been invoked.
Will the OS keep the network connection / file descriptor / whatever open? Will the garbage collector do something or will something even prevent it from touching that struct?
I.e.
conn, _ := net.DialTCP(network, laddr, raddr)
// do stuff, then
conn = nil
// forgot to invoke `Close()`!!
// what happens now?
Such closeable resources may have finalizers set with runtime.SetFinalizer, for example the netFD of TCPListener:
runtime.SetFinalizer(fd, (*netFD).Close)
This should not be a reason for omitting to call Close() to free resources, also because there is no guarantee that the finalizer will be called or when:
The finalizer is scheduled to run at some arbitrary time after the program can no longer reach the object to which obj points. 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.
Call Close() to make sure the resources are freed.
Related:
Which objects are finalized in Go by default and what are some of the pitfalls of it?
Os will keep the file descriptors for non-closed connections, which is going to be freed once the program exits.

Is it necessary to free a mutex created by xSemaphoreCreateMutex()?

FreeRTOS and ESP-IDF provide xSemaphoreCreateMutex() which allocates and initializes a mutex. Their docs say:
If a mutex is created using xSemaphoreCreateMutex() then the required
memory is automatically dynamically allocated inside the
xSemaphoreCreateMutex() function. (see
http://www.freertos.org/a00111.html).
However, I can't find any info on whether it is necessary to free the memory created by the mutex. This would be important if using C++ with a mutex member variable, like:
class MyClass
{
MyClass::MyClass()
{
mAccessMutex = xSemaphoreCreateMutex();
}
MyClass::~MyClass()
{
// What to do here??
}
SemaphoreHandle_t mAccessMutex;
}
REFERENCE
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html?highlight=xsemaphore#semaphore-api
According to FreeRTOS API reference, the proper way to destroy/delete a mutex is vSemaphoreDelete()
Deletes a semaphore, including mutex type semaphores and recursive
semaphores.
Do not delete a semaphore that has tasks blocked on it.
If you're using heap_1, deleting is not possible. Also, make sure that you fully understand the perils of dynamic memory allocation in embedded systems before using it. If MyClass is going to be created and destroyed in a regular/periodic basis, this may cause problems.
So yes, it's necessary to call vSemaphoreDelete(mAccessMutex) in ~MyClass(). But it's probably best to make sure that MyClass instances never get destroyed. In my projects, I generally use one-time dynamic allocation during initialization and forget to implement a proper destructor (which is a bad habit that I need to fix).

What happens to stack/heap allocated types when a runtime panic occurs?

What happens to the types that are allocated on the heap or stack before a panic occurs? Is a destructor called so that the types are deallocated? Do they linger around in the memory waiting to be overwritten by some other process? Or is it something else entirely?
I've no idea since I'm new to Rust and systems programming in general.
By default, the stack will be unwound and destructors are run. You can prove this for yourself:
struct Noisy;
impl Drop for Noisy {
fn drop(&mut self) {
println!("Dropping!");
}
}
fn main() {
let _on_stack = Noisy;
let _on_heap = Box::new(Noisy);
panic!("Oh no!");
}
This will print:
Dropping!
Dropping!
Note that there's no real difference in stack or heap here. Any heap-allocated item is going to have something on the stack pointing to it. When the handle on the stack goes out of scope, it cleans up the heap resources.
The stack is unwound until it exits from the current thread (if it's the main thread, the program exits). It's also possible to use catch_unwind. Beware using this though:
It is not recommended to use this function for a general try/catch mechanism. [...] Note that this function may not catch all panics in Rust.
Note that I said by default. You can also compile with an option whereby panics translate directly into aborting the process. At that point, the process is over and no more destructors will be run.
If you panic in a destructor, then it's also game over: the process will be aborted.

Can I explicitly invoke property destructors so that I can see which one causes problems?

I guess this is a really nasty issue - seems like one of the property destructors of my class creates deadlock. Property destructors are called automatically after class destructor. And I'd like to call them manually and make a log entry after every single one succeeds.
The problem only occurs on devices, where debugger can't be used, so I am using log instead.
Client::~Client() {
// Stops io service and disconnects sockets
exit();
LOG("io_service stopped"<<endl);
// Destroy IO service
io_.~io_service();
LOG("io_service destroyed"<<endl);
}
But the code above actually causes exception, because the ~io_service() gets called twice.
So is there a way to do this properly? If not, what's an alternative to debugging destructors?
You can't alter the compiler behaviour like that. the compiler will augment the destructor to destruct nested objects.
What you can do is to declare io as a pointer and allocate it dynamically with new. then call delete io and monitor what happens there.
Other solution is just to put a breakpoint on the io destructor and follow what happens there upon destruction. this is probably the best idea.

Free C pointer when collected by GC

I have a package that interfaces with a C library. Now I need to store a pointer to a C struct in the Go struct
type A struct {
s *C.struct_b
}
Obviously this pointer needs to be freed before the struct is collected by the GC. How can I accomplish that?
The best thing to do is when possible copy the C struct into go controlled memory.
var ns C.struct_b
ns = *A.s
A.s = &ns
Obviously, that won't work in all cases. C.struct_b may be too complicated or shared with something still in C code. In this case, you need to create a .Free() or .Close() method (whichever makes more sense) and document that the user of your struct must call it. In Go, a Free method should always be safe to call. For example, after free is run, be sure to set A.s = nil so that if the user calls Free twice, the program does not crash.
There is also a way to create finalizers. See another answer I wrote here. However, they may not always run and if garbage is created fast enough, it is very possible that the creation of garbage will out pace collection. This should be considered as a supplement to having a Free/Close method and not a replacement.

Resources