[Gc] GC_INIT? Threads?
Bruce Hoult
bruce at hoult.org
Tue Aug 20 06:37:45 PDT 2013
It would be helpful to know where it hangs. Do you not have access to a
debugger? It's also almost impossible to help without seeing the full
source code for a program that shows the problem. There are an almost
infinite number of things that *could* be done incorrectly.
For example, do you know whether GC_get_stack_base() is returning? Are you
checking its return value for GC_SUCCESS? Does GC_register_my_thread()
return? Does it return GC_SUCCESS?
If you are not using IA64 then this should be pretty foolproof:
void foo_thread(){
struct GC_stack_base my_sb;
my_sb.mem_base = &my_sb;
GC_register_my_thread(&my_sb);
foo_thread_inner();
GC_unregister_my_thread();
}
void foo_thread_inner(){
// do the real work here
}
On Wed, Aug 21, 2013 at 1:10 AM, The Devils Jester <
thedevilsjester at gmail.com> wrote:
> I do not know what you mean about the error.
>
> In the first scenario, without the register threads functions, it outputs
> the error I posted above :
> "Collecting from unknown thread
> Abort trap: 6"
>
> In the second scenario, with the additional functions, it enters an
> endless loop and never (within the few minutes I let it sit for) errors.
>
> I only include gc_cpp.h, and only once. I have #define GC_THREADS
> directly before the include.
>
> Is there any additional information I can provide?
>
> Must I use GC_call_with_stack_base()? If so, how is this function used?
>
> Is there a way I can tell if the GC was built without GC_THREADS support?
> Wouldnt it be missing the above mentioned thread symbols from the library
> if this were the case?
>
>
>
> On Tue, Aug 20, 2013 at 1:22 AM, Bruce Hoult <bruce at hoult.org> wrote:
>
>> It's really very hard to tell without knowing what error the GC is
>> detecting and aborting on (it writes the message to stderr), and without
>> being able to see your source code.
>>
>> It could be as basic as your GC library not having been built to support
>> threads, or your client program not having done "#define GC_THREADS"
>> before including gc.h.
>>
>> You can define the GC_LOOP_ON_ABORT environment variable, in which case
>> GC_abort() will sit in an infinite loop so you can attach to the process
>> and debug it. But then you could also have just set a breakpoint in
>> GC_abort() to achieve the same end.
>>
>>
>> On Tue, Aug 20, 2013 at 6:08 PM, The Devils Jester <
>> thedevilsjester at gmail.com> wrote:
>>
>>> I apologize, I do not mean "crash" in the literal sense. I appreciate
>>> the help finding a solution to my problem.
>>>
>>> The commands supplied, causes the program to lock up and consume all of
>>> the CPU.
>>>
>>> The code I have is as follows. I am unsure about the stack_base or how
>>> it is used.
>>>
>>> In my primary thread:
>>> GC_INIT();
>>> GC_allow_register_threads();
>>> ClassFromMyLib * myclass = new ClassFromMyLib();
>>>
>>> In my new thread:
>>> struct GC_stack_base *my_sb;
>>> GC_get_stack_base(my_sb);
>>> GC_register_my_thread(my_sb);
>>> myclass->myfunction();
>>> GC_unregister_my_thread();
>>>
>>> Without the special GC_ functions, everything works fine until GC tries
>>> to reclaim memory, with them it locks up.
>>>
>>> Am I doing something wrong?
>>>
>>>
>>>
>>>
>>> On Tue, Aug 20, 2013 at 12:00 AM, Bruce Hoult <bruce at hoult.org> wrote:
>>>
>>>> Once again, it's not crashing, it's a controlled exit because it
>>>> detected something wrong.
>>>>
>>>> Try using these (from gc.h)
>>>>
>>>> call GC_allow_register_threads() from your main program, after GC_INIT()
>>>> call GC_register_my_thread() at the start of the main function for each
>>>> thread you create. (and GC_unregister_my_thread() at the end)
>>>>
>>>> You may also find GC_call_with_stack_base() useful.
>>>>
>>>> /* Explicitly enable GC_register_my_thread() invocation.
>>>> */
>>>> /* Done implicitly if a GC thread-creation function is called (or
>>>> */
>>>> /* implicit thread registration is activated). Otherwise, it must
>>>> */
>>>> /* be called from the main (or any previously registered) thread
>>>> */
>>>> /* between the collector initialization and the first explicit
>>>> */
>>>> /* registering of a thread (it should be called as late as possible).
>>>> */
>>>> GC_API void GC_CALL GC_allow_register_threads(void);
>>>>
>>>> /* Register the current thread, with the indicated stack base, as
>>>> */
>>>> /* a new thread whose stack(s) should be traced by the GC. If it
>>>> */
>>>> /* is not implicitly called by the GC, this must be called before a
>>>> */
>>>> /* thread can allocate garbage collected memory, or assign pointers
>>>> */
>>>> /* to the garbage collected heap. Once registered, a thread will be
>>>> */
>>>> /* stopped during garbage collections.
>>>> */
>>>> /* This call must be previously enabled (see above).
>>>> */
>>>> /* This should never be called from the main thread, where it is
>>>> */
>>>> /* always done implicitly. This is normally done implicitly if GC_
>>>> */
>>>> /* functions are called to create the thread, e.g. by including gc.h
>>>> */
>>>> /* (which redefines some system functions) before calling the system
>>>> */
>>>> /* thread creation function. Nonetheless, thread cleanup routines
>>>> */
>>>> /* (eg., pthread key destructor) typically require manual thread
>>>> */
>>>> /* registering (and unregistering) if pointers to GC-allocated
>>>> */
>>>> /* objects are manipulated inside.
>>>> */
>>>> /* It is also always done implicitly on some platforms if
>>>> */
>>>> /* GC_use_threads_discovery() is called at start-up. Except for the
>>>> */
>>>> /* latter case, the explicit call is normally required for threads
>>>> */
>>>> /* created by third-party libraries.
>>>> */
>>>> /* A manually registered thread requires manual unregistering.
>>>> */
>>>> GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base
>>>> *);
>>>>
>>>> /* Unregister the current thread. Only an explicitly registered
>>>> */
>>>> /* thread (i.e. for which GC_register_my_thread() returns GC_SUCCESS)
>>>> */
>>>> /* is allowed (and required) to call this function. (As a special
>>>> */
>>>> /* exception, it is also allowed to once unregister the main thread.)
>>>> */
>>>> /* The thread may no longer allocate garbage collected memory or
>>>> */
>>>> /* manipulate pointers to the garbage collected heap after making
>>>> */
>>>> /* this call. Specifically, if it wants to return or otherwise
>>>> */
>>>> /* communicate a pointer to the garbage-collected heap to another
>>>> */
>>>> /* thread, it must do this before calling GC_unregister_my_thread,
>>>> */
>>>> /* most probably by saving it in a global data structure. Must not
>>>> */
>>>> /* be called inside a GC callback function (except for
>>>> */
>>>> /* GC_call_with_stack_base() one).
>>>> */
>>>> GC_API int GC_CALL GC_unregister_my_thread(void);
>>>>
>>>>
>>>>
>>>> On Tue, Aug 20, 2013 at 4:48 PM, The Devils Jester <
>>>> thedevilsjester at gmail.com> wrote:
>>>>
>>>>> The only output I get, aside from the stack trace is:
>>>>> Collecting from unknown thread
>>>>> Abort trap: 6
>>>>>
>>>>> My application is organized as follows:
>>>>>
>>>>> MAIN APP (does not use GC)
>>>>> GC_INIT()
>>>>> NEW THREAD
>>>>> CALL LIBRARY FUNCTION (library uses GC)
>>>>>
>>>>> This crashes, while
>>>>>
>>>>> MAIN APP (does not use GC)
>>>>> GC_INIT()
>>>>> CALL LIBRARY FUNCTION (library uses GC)
>>>>>
>>>>> Works perfectly fine.
>>>>>
>>>>> What am I doing wrong? Do I have to initialize the GC in some special
>>>>> fashion?
>>>>>
>>>>>
>>>>> On Mon, Aug 19, 2013 at 11:35 PM, Bruce Hoult <bruce at hoult.org> wrote:
>>>>>
>>>>>> That's not a crash, it's a deliberate abort because some
>>>>>> sanity-checking code found that your world was insane. There are several
>>>>>> things that can go wrong inside GC_push_all_stacks, so it would be
>>>>>> helpful to have the message that GC_abort() printed.
>>>>>>
>>>>>> However, you should always call GC_INIT() from your main program, and
>>>>>> as early as possible.
>>>>>>
>>>>>> On some versions and platforms GC_INIT() installs code that registers
>>>>>> threads in a GC data structure because it's not possible to ask the OS for
>>>>>> all your threads. If you call GC_INIT() from a new thread on those
>>>>>> platforms then that thread will remain unregistered, which is one of the
>>>>>> things that will make GC_push_all_stacks abort later.
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Tue, Aug 20, 2013 at 4:10 PM, The Devils Jester <
>>>>>> thedevilsjester at gmail.com> wrote:
>>>>>>
>>>>>>> I have a library that makes heavy use of of the GC, and it works
>>>>>>> quite well when everything (the app, and the library) is in one thread. I
>>>>>>> call GC_INIT in the app, and all is well.
>>>>>>>
>>>>>>> If, however, the app creates a new thread that calls the library
>>>>>>> function, then it crashes when the GC does its magic (below I have pasted
>>>>>>> some relevant output).
>>>>>>>
>>>>>>> Is there some trick to using GC on a separate thread? Do I call
>>>>>>> GC_INIT from the main thread, or the one that calls the library functions?
>>>>>>>
>>>>>>>
>>>>>>> 0 libsystem_kernel.dylib 0x00007fff8ad14212
>>>>>>> __pthread_kill + 10
>>>>>>> 1 libsystem_c.dylib 0x00007fff90d01b54 pthread_kill +
>>>>>>> 90
>>>>>>> 2 libsystem_c.dylib 0x00007fff90d45dce abort + 143
>>>>>>> 3 libgc.1.dylib 0x000000010357676e GC_abort + 97
>>>>>>> 4 libgc.1.dylib 0x000000010357b413
>>>>>>> GC_push_all_stacks + 285
>>>>>>> 5 libgc.1.dylib 0x000000010357396e GC_mark_some +
>>>>>>> 377
>>>>>>> 6 libgc.1.dylib 0x000000010356d73e
>>>>>>> GC_stopped_mark + 148
>>>>>>> 7 libgc.1.dylib 0x000000010356d645
>>>>>>> GC_try_to_collect_inner + 245
>>>>>>> 8 libgc.1.dylib 0x000000010356e302
>>>>>>> GC_collect_or_expand + 147
>>>>>>> 9 libgc.1.dylib 0x000000010356e51a GC_allocobj +
>>>>>>> 228
>>>>>>> 10 libgc.1.dylib 0x0000000103572515
>>>>>>> GC_generic_malloc_inner + 249
>>>>>>> 11 libgc.1.dylib 0x00000001035725dd
>>>>>>> GC_generic_malloc + 79
>>>>>>> 12 libgc.1.dylib 0x00000001035728c0 GC_core_malloc
>>>>>>> + 196
>>>>>>>
>>>>>>> --
>>>>>>> This message has been scanned for viruses and
>>>>>>> dangerous content by *MailScanner* <http://www.mailscanner.info/>,
>>>>>>> and is
>>>>>>> believed to be clean.
>>>>>>> _______________________________________________
>>>>>>> Gc mailing list
>>>>>>> Gc at linux.hpl.hp.com
>>>>>>> http://www.hpl.hp.com/hosted/linux/mail-archives/gc/
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>> --
>>>>> This message has been scanned for viruses and
>>>>> dangerous content by *MailScanner* <http://www.mailscanner.info/>,
>>>>> and is
>>>>> believed to be clean.
>>>>>
>>>>
>>>>
>>>
>>> --
>>> This message has been scanned for viruses and
>>> dangerous content by *MailScanner* <http://www.mailscanner.info/>, and
>>> is
>>> believed to be clean.
>>>
>>
>>
>
> --
> This message has been scanned for viruses and
> dangerous content by *MailScanner* <http://www.mailscanner.info/>, and is
> believed to be clean.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://napali.hpl.hp.com/pipermail/gc/attachments/20130821/a7aef261/attachment-0001.htm
More information about the Gc
mailing list