FAQ
When a finalizer function is set with runtime.SetFinalizer(), it is run in
a dedicated goroutine, after GC has finished its work.
It means that the finalizer function runs in parrallel with the main and
other threads of the program.
This little program illustrate this:
   http://play.golang.org/p/KLrhppn5k5

This means that the finalizer function must be goroutine-safe (access to
shared memory must be synchronized).

But finalizers are often used to release resources.

Let's have the following scenario:

We use cgo with C code to access a database.

We create a Connection object, which is just a proxy struct to a connection
object inside C world.
We also set a finalizer function to this Connection object, so that it
calls a Close() function on it if it goes out of scope.
This Close() function calls many times a "free()" function of a custom
memory allocator THAT IS NON-THREAD-SAFE.

Eventually, the Connection object goes out of scope, and GC schedules the
finalizer to run soon on its dedicated goroutine.

As GC finishes, the main goroutine resumes its work, creating and deleting
other database objects by calling proper C functions of the database API.
Suddenly, the finalizer runs.

The problem is that if the finalizer calls "free()" to our custom memory
allocator in the C world, and that the main goroutine is also calling a
"alloc()" or "free()" function on this allocator at the same time, it will
corrupt this memory allocator. Indeed, the allocator is not thread-safe by
design, because the author wanted to dedicate a fast allocator per each
connection object.
It was not expected, and even forbidden, that two threads access at the
same time this custom allocator.
But by setting a finalizer, it is what happens.


Presently, I am tracking a nasty bug that occurs very rarely, only once in
a hundred or thousand executions of the same program with same input.
This program runs only on one goroutine. When a crash occurs, it is always
a segfault, due to corruption of the custom memory allocator.
The stacktrace shows that it never occurs at the same place, indicating
that the cause must be asynchronous.
The corruption of the memory allocator can occur when two OS threads access
it at the same time.

I imagine that the finalizer is the cause of this bug.
And I have some questions:

1) when GOMAXPROCS is unset, or set to 1, we can have two OS threads
running in parrallel (main thread + finalizer thread) ?

2) the GC never interrupts a cgo call that is executing ? When there are
many threads, GC waits for the threads to come at a rendez-vous point
before running ?

3) if the resource allocator is not thread-safe, how use it in a finalizer ?


--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Branimir Maksimovic at Nov 8, 2014 at 2:17 am

    On Saturday, November 8, 2014 2:37:10 AM UTC+1, nicolas...@gmail.com wrote:
    When a finalizer function is set with runtime.SetFinalizer(), it is run in
    a dedicated goroutine, after GC has finished its work.
    It means that the finalizer function runs in parrallel with the main and
    other threads of the program.
    This little program illustrate this:
    http://play.golang.org/p/KLrhppn5k5

    This means that the finalizer function must be goroutine-safe (access to
    shared memory must be synchronized).

    But finalizers are often used to release resources.
    I never use finalizer to release resources. Only use for finalizer is debug
    and
    I have special case when I need to make object alive (when referenced from
    C code), by non stop resetting
    finalizer until C code sets variable which indicates that object should be
    collected.
    eg user data that is referenced from C++ object which calls Go event
    handling function.
    But resource handling in finalizer is not good as finalizers are not run
    immediately.
    There is `defer` for that.


    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Dave Cheney at Nov 8, 2014 at 3:51 am
    Finalisers are not guaranteed to be run, ever. It is not a bug if a finaliser is never run, the runtime does not guarantee that the finaliser will ever run.

    Please don't use a finaliser.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Taylor at Nov 8, 2014 at 5:27 am

    On Fri, Nov 7, 2014 at 5:37 PM, wrote:
    1) when GOMAXPROCS is unset, or set to 1, we can have two OS threads running
    in parrallel (main thread + finalizer thread) ?
    You can't have two Go threads running in parallel, but you can have a
    finalizer Go thread running in parallel with a C thread.

    2) the GC never interrupts a cgo call that is executing ? When there are
    many threads, GC waits for the threads to come at a rendez-vous point before
    running ?
    GC can run during a long-running cgo call.

    3) if the resource allocator is not thread-safe, how use it in a finalizer ?
    Have the finalizer adds objects to a queue, and have a goroutine that
    free items on the queue holding appropriate locks.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Marvin Humphrey at Nov 11, 2014 at 4:09 am
  • Adonovan at Nov 11, 2014 at 2:23 am

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedNov 8, '14 at 1:37a
activeNov 11, '14 at 4:09a
posts6
users6
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase