diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index b93c944a8c..58e7625ced 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -76,6 +76,8 @@ jobs: - name: Check improts run: | + export $(go env | grep GOROOT | sed 's/\"//g') + echo $GOROOT imports-formatter -path . git status && [[ -z `git status -s` ]] diff --git a/common/proxy/proxy_factory/default.go b/common/proxy/proxy_factory/default.go index d8b9ea1ff1..926dc17786 100644 --- a/common/proxy/proxy_factory/default.go +++ b/common/proxy/proxy_factory/default.go @@ -137,28 +137,31 @@ func (pi *ProxyInvoker) Invoke(ctx context.Context, invocation protocol.Invocati // prepare replyv var replyv reflect.Value - //if method.ReplyType() == nil && len(method.ArgsType()) > 0 { - // - // replyv = reflect.New(method.ArgsType()[len(method.ArgsType())-1].Elem()) - // in = append(in, replyv) - //} + var retErr interface{} - returnValues := method.Method().Func.Call(in) + returnValues, callErr := callLocalMethod(method.Method(), in) + + if callErr != nil { + logger.Errorf("Invoke function error: %+v, service: %#v", callErr, url) + result.SetError(callErr) + return result + } - var retErr interface{} if len(returnValues) == 1 { retErr = returnValues[0].Interface() } else { replyv = returnValues[0] retErr = returnValues[1].Interface() } + if retErr != nil { result.SetError(retErr.(error)) - } else { - if replyv.IsValid() && (replyv.Kind() != reflect.Ptr || replyv.Kind() == reflect.Ptr && replyv.Elem().IsValid()) { - result.SetResult(replyv.Interface()) - } + return result } + if replyv.IsValid() && (replyv.Kind() != reflect.Ptr || replyv.Kind() == reflect.Ptr && replyv.Elem().IsValid()) { + result.SetResult(replyv.Interface()) + } + return result } diff --git a/common/proxy/proxy_factory/pass_through.go b/common/proxy/proxy_factory/pass_through.go index 41a2b57316..38cb2581b6 100644 --- a/common/proxy/proxy_factory/pass_through.go +++ b/common/proxy/proxy_factory/pass_through.go @@ -30,6 +30,7 @@ import ( "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/common/logger" "dubbo.apache.org/dubbo-go/v3/common/proxy" "dubbo.apache.org/dubbo-go/v3/protocol" ) @@ -106,10 +107,18 @@ func (pi *PassThroughProxyInvoker) Invoke(ctx context.Context, invocation protoc in = append(in, reflect.ValueOf(args)) in = append(in, reflect.ValueOf(invocation.Attachments())) - returnValues := method.Method().Func.Call(in) - + var replyv reflect.Value var retErr interface{} - replyv := returnValues[0] + + returnValues, callErr := callLocalMethod(method.Method(), in) + + if callErr != nil { + logger.Errorf("Invoke function error: %+v, service: %#v", callErr, url) + result.SetError(callErr) + return result + } + + replyv = returnValues[0] retErr = returnValues[1].Interface() if retErr != nil { @@ -119,5 +128,6 @@ func (pi *PassThroughProxyInvoker) Invoke(ctx context.Context, invocation protoc if replyv.IsValid() && (replyv.Kind() != reflect.Ptr || replyv.Kind() == reflect.Ptr && replyv.Elem().IsValid()) { result.SetResult(replyv.Interface()) } + return result } diff --git a/common/proxy/proxy_factory/utils.go b/common/proxy/proxy_factory/utils.go new file mode 100644 index 0000000000..44af7d28c0 --- /dev/null +++ b/common/proxy/proxy_factory/utils.go @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package proxy_factory + +import ( + "fmt" + "reflect" +) + +import ( + perrors "github.com/pkg/errors" +) + +// CallLocalMethod is used to handle invoke exception in user func. +func callLocalMethod(method reflect.Method, in []reflect.Value) ([]reflect.Value, error) { + var ( + returnValues []reflect.Value + retErr error + ) + + func() { + defer func() { + if e := recover(); e != nil { + if err, ok := e.(error); ok { + retErr = err + } else if err, ok := e.(string); ok { + retErr = perrors.New(err) + } else { + retErr = fmt.Errorf("invoke function error, unknow exception: %+v", e) + } + } + }() + + returnValues = method.Func.Call(in) + }() + + if retErr != nil { + return nil, retErr + } + + return returnValues, retErr +} diff --git a/remoting/getty/listener.go b/remoting/getty/listener.go index f9d5107662..89fc961c29 100644 --- a/remoting/getty/listener.go +++ b/remoting/getty/listener.go @@ -18,7 +18,6 @@ package getty import ( - "fmt" "sync" "sync/atomic" "time" @@ -265,27 +264,6 @@ func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) { return } - defer func() { - if e := recover(); e != nil { - resp.Status = hessian.Response_SERVER_ERROR - if err, ok := e.(error); ok { - logger.Errorf("OnMessage panic: %+v, req: %#v", perrors.WithStack(err), req.Data) - resp.Error = perrors.WithStack(err) - } else if err, ok := e.(string); ok { - logger.Errorf("OnMessage panic: %+v, req: %#v", perrors.New(err), req.Data) - resp.Error = perrors.New(err) - } else { - logger.Errorf("OnMessage panic: %+v, this is impossible. req: %#v", e, req.Data) - resp.Error = fmt.Errorf("OnMessage panic unknow exception. %+v", e) - } - - if !req.TwoWay { - return - } - reply(session, resp) - } - }() - invoc, ok := req.Data.(*invocation.RPCInvocation) if !ok { panic("create invocation occur some exception for the type is not suitable one.") @@ -299,6 +277,7 @@ func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) { return } resp.Result = result + reply(session, resp) }