So, to give more background, i am trying to porting a C based interpreter to Go. In the single threaded C code, the signal is always handled by interrupting whatever code was executing and directly exit after executing some "crash()" cleanup function.
Now, I ported the main function to Go, as I demonstrated above, there is no way to "interrupt" C code anymore, so I can't run crash() cleanly as before. This seems to be a limitation of Go, and I couldn't think of any way to work around it. On Wed, Feb 15, 2017 at 10:35 AM, Axel Wagner <[email protected]> wrote: > You misunderstood what I was trying to do (the recover was supposed to > recover from any panic raised by the C-code, not from the panic of the main > loop). And just added a new requirement. > > I don't think what you want is possible, from what I know about the go > runtime. You could approximate it, by running C.do_anything and reading from > the signal-channel alternately, but that would still delay any signal > handling to after your C-code is done. > > But your requirements also seems more and more obscure to me; I could kind > of understand why the C code and the cleanup code must run in the same > goroutine/thread, but it seems obscure, that the asynchronous signal > handling *also* needs to run in that thread. > > Anyway. Maybe someone else knows more about all of this than me and can help > you :) > > On Wed, Feb 15, 2017 at 7:26 PM, Yucong Sun <[email protected]> wrote: >> >> Also, my cleanup function must be tied directly with C loop, because >> they are sharing the same underlaying memory/state . If I directly >> run cleanup() while C loop was running, there could be race. >> >> So that leaves me with no choice, i must be able to panic on the C >> loop's go-routine on async signals, which I can't do with current >> tools. >> >> On Wed, Feb 15, 2017 at 10:21 AM, Yucong Sun <[email protected]> wrote: >> > https://play.golang.org/p/7Vz0o4ZoQF >> > >> > shows that your code doesn't really work. My understanding is once >> > panic reaches the current goroutine's top of callstack, program will >> > crash, there are no attempt to call other goroutine's deferred >> > function. >> > >> > So, in order to do what I want, i must be able to trigger some sort >> > of inline panic remotely. Note in the C code this is easy, the >> > signal handler will interrupt current thread, jump directly to the >> > handler code and resume. If I can do that in golang, i will be able >> > to trigger a panic in main() and do what I want (or do what the old C >> > code does, which i was porting into go) >> > >> > On Wed, Feb 15, 2017 at 10:14 AM, Yucong Sun <[email protected]> >> > wrote: >> >> Thanks axle, but are you sure the code would work? it is essentially >> >> triggering panic on the main go routine while recovering from another >> >> goroutine, isn't that impossible? >> >> >> >> If this is possible, why couldn't I trigger a panic on a goroutine >> >> then recover it from main goroutine? >> >> >> >> On Wed, Feb 15, 2017 at 10:03 AM, Axel Wagner >> >> <[email protected]> wrote: >> >>> First, the code you wrote here doesn't use os/signal, so you can't >> >>> really >> >>> fault Ian for giving that advice. Here's my understanding: >> >>> >> >>> In general, there are two kinds of signals: synchronous ones, raised >> >>> e.g. by >> >>> dereferencing invalid memory. They produce a runtime panic at the site >> >>> that >> >>> produced them in the corresponding goroutine. And asynchronous ones, >> >>> raised >> >>> e.g. by using the kill command or os.Kill. They do not produce a >> >>> runtime >> >>> panic but instead need to be handled via os/signal. >> >>> >> >>> Now, to "catch" asynchronous panic's, you need to use os/signal and if >> >>> you >> >>> need them to produce a runtime-panic on the goroutine running main, >> >>> you need >> >>> to read from that channel in main and produce a panic whenever you >> >>> read a >> >>> value. You could, for example, do this: >> >>> >> >>> func main() { >> >>> ch := make(chan os.Signal) >> >>> signal.Notify(ch, mySignals) >> >>> >> >>> errs := make(chan interface{}) >> >>> >> >>> go func() { >> >>> defer func() { >> >>> errs <- recover() >> >>> }() >> >>> for { >> >>> C.do_something() >> >>> } >> >>> }() >> >>> >> >>> for { >> >>> select { >> >>> case s := <-ch: >> >>> panic(fmt.Sprintf("received signal: %v", s)) >> >>> case v := <-errs: >> >>> panic(fmt.Sprintf("recovered runtime panic in C-code: %v", >> >>> v)) >> >>> } >> >>> } >> >>> } >> >>> >> >>> this will get asynchronous signals via os/signal and synchronous >> >>> signals in >> >>> the C-code raising runtime-panics via recover. >> >>> >> >>> Now, what is *not* possible, is to somehow recover from runtime panics >> >>> caused by synchronous signals in *other* goroutines. The spec is >> >>> pretty >> >>> clear about that; a panic that isn't recovered will cause the program >> >>> to >> >>> crash. >> >>> >> >>> Hope this helps. >> >>> >> >>> On Wed, Feb 15, 2017 at 6:44 PM, Yucong Sun <[email protected]> >> >>> wrote: >> >>>> >> >>>> hi, >> >>>> >> >>>> Maybe I wasn't clear, I am indeed using os.signal package. But it >> >>>> doesn't >> >>>> do what I want! I want to trigger a panic in main function , seems >> >>>> there is >> >>>> no way to do it by using a signal channel . >> >>>> >> >>>> Thanks >> >>>> >> >>>> -- >> >>>> 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 [email protected]. >> >>>> 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 [email protected]. For more options, visit https://groups.google.com/d/optout.
