Will two Go runtimes in the same process collide over signals/other?

233 views
Skip to first unread message

Jason E. Aten

unread,
Oct 3, 2022, 2:26:20 AM10/3/22
to golang-nuts
I've tried to come to grips with the lovingly detailed https://pkg.go.dev/os/signal preamble, but I'm going to ask to get the experts thoughts. On Linux, my scenario is:

I have a main program main.go.  Via CGO, it loads libmyc.so, a large, legacy, C .so shared library.  Obviously the executable of main.go will contain a Go runtime.

I have a separate c-shared library, as a libmygolib.so, that I've written in Go. Since
it is a c-shared .so, it will contain a Go runtime as well.

Now libmyc.so would like to load and use libmygolib.so.

As a result I'll have two Go runtimes in the same process, possibly fighting over
signal handlers.

I don't really care about profiling here; I can run them independently for debugging/tuning.

Am I going to get signal handling problems?  Is there anything I can do with the signal handling to avoid them?

Is there some way to build a c-shared library so it will not have the Go runtime in it, and have the dynamic linker find the single Go runtime at load time?

Thank you.

Ian Lance Taylor

unread,
Oct 3, 2022, 11:33:42 PM10/3/22
to Jason E. Aten, golang-nuts
On Sun, Oct 2, 2022 at 11:26 PM Jason E. Aten <j.e....@gmail.com> wrote:
>
> I've tried to come to grips with the lovingly detailed https://pkg.go.dev/os/signal preamble, but I'm going to ask to get the experts thoughts. On Linux, my scenario is:
>
> I have a main program main.go. Via CGO, it loads libmyc.so, a large, legacy, C .so shared library. Obviously the executable of main.go will contain a Go runtime.
>
> I have a separate c-shared library, as a libmygolib.so, that I've written in Go. Since
> it is a c-shared .so, it will contain a Go runtime as well.
>
> Now libmyc.so would like to load and use libmygolib.so.
>
> As a result I'll have two Go runtimes in the same process, possibly fighting over
> signal handlers.
>
> I don't really care about profiling here; I can run them independently for debugging/tuning.
>
> Am I going to get signal handling problems? Is there anything I can do with the signal handling to avoid them?

It's possible. On Linux the dynamic linker may override all the
shared library symbols with the symbols in the main programs. I'm not
sure, and in general it will depend on how the main program is linked.
If it does override, then the duplication of the runtime may not
matter. I'm not really sure, though.

> Is there some way to build a c-shared library so it will not have the Go runtime in it, and have the dynamic linker find the single Go runtime at load time?

There is not.

Ian

Jason E. Aten

unread,
Oct 4, 2022, 12:17:09 AM10/4/22
to golang-nuts
On Monday, October 3, 2022 at 10:33:42 PM UTC-5 Ian Lance Taylor wrote:

> Am I going to get signal handling problems? Is there anything I can do with the signal handling to avoid them?

It's possible. On Linux the dynamic linker may override all the
shared library symbols with the symbols in the main programs. I'm not
sure, and in general it will depend on how the main program is linked.
If it does override, then the duplication of the runtime may not
matter. I'm not really sure, though.

Thank you, Ian.  Super helpful as always.

To follow up on that intriguing thought about the dynamic linker, how would I tell if the dynamic linker has overridden symbols? 
Moreover, which flags on the main program would affect this? 

Lastly, could I clarify one part in the https://pkg.go.dev/os/signal#hdr-Non_Go_programs_that_call_Go_code  docs:

"For the synchronous signals and SIGPIPE, the Go runtime will install a signal handler. 
It will save any existing signal handler. If a synchronous signal arrives while executing 
non-Go code, the Go runtime will invoke the existing signal handler instead of the Go signal handler."

Would the two Go runtimes be able to distinguish themselves from each other?  The main.go runtime is built as a regular Go program. The c-shared 
runtime is, well, built under c-shared, so it will have a different stack space and different default signal handling.
(I'm thinking of this part of the same os/signal section linked above:

"Go code built without -buildmode=c-archive or -buildmode=c-shared will install a signal handler for the 
asynchronous signals listed above, and save any existing signal handler. If a signal is delivered to a non-Go thread, 
it will act as described above, except that if there is an existing non-Go signal handler, that handler will be 
installed before raising the signal.")


 

Ian Lance Taylor

unread,
Oct 4, 2022, 7:27:35 PM10/4/22
to Jason E. Aten, golang-nuts
On Mon, Oct 3, 2022 at 9:17 PM Jason E. Aten <j.e....@gmail.com> wrote:
>
> On Monday, October 3, 2022 at 10:33:42 PM UTC-5 Ian Lance Taylor wrote:
>>
>>
>> > Am I going to get signal handling problems? Is there anything I can do with the signal handling to avoid them?
>>
>> It's possible. On Linux the dynamic linker may override all the
>> shared library symbols with the symbols in the main programs. I'm not
>> sure, and in general it will depend on how the main program is linked.
>> If it does override, then the duplication of the runtime may not
>> matter. I'm not really sure, though.
>
>
> Thank you, Ian. Super helpful as always.
>
> To follow up on that intriguing thought about the dynamic linker, how would I tell if the dynamic linker has overridden symbols?

It might be hard. One approach might be to call runtime.Callers(0)
both in the main program and in the shared library. If symbols are
overridden then pc[0] should be the same for both.

> Moreover, which flags on the main program would affect this?

Things like the C linker's -Bsymbolic or --exclude-libs options.

> Lastly, could I clarify one part in the https://pkg.go.dev/os/signal#hdr-Non_Go_programs_that_call_Go_code docs:
>
> "For the synchronous signals and SIGPIPE, the Go runtime will install a signal handler.
> It will save any existing signal handler. If a synchronous signal arrives while executing
> non-Go code, the Go runtime will invoke the existing signal handler instead of the Go signal handler."
>
> Would the two Go runtimes be able to distinguish themselves from each other? The main.go runtime is built as a regular Go program. The c-shared
> runtime is, well, built under c-shared, so it will have a different stack space and different default signal handling.
> (I'm thinking of this part of the same os/signal section linked above:
>
> "Go code built without -buildmode=c-archive or -buildmode=c-shared will install a signal handler for the
> asynchronous signals listed above, and save any existing signal handler. If a signal is delivered to a non-Go thread,
> it will act as described above, except that if there is an existing non-Go signal handler, that handler will be
> installed before raising the signal.")

That is an interesting question. It's quite possible that when a
signal occurs the shared library will check whether the signal is
occurring within the shared library, and, if not, will call the main
program's signal handler. The code makes no attempt to tell whether
the existing signal handler is installed by Go. It just treats it as
something to call if it doesn't want to handle the signal itself.

Ian
Reply all
Reply to author
Forward
0 new messages