如果Fabric的智能合约函数陷入死循环会怎么样

Posted powervip

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果Fabric的智能合约函数陷入死循环会怎么样相关的知识,希望对你有一定的参考价值。

大家好,我是powervip!今天和大家一起探讨一下:如果Fabric的智能合约函数陷入死循环会怎么样

先看一段合约函数代码:

func (t *SimpleChaincode) Test(stub shim.ChaincodeStubInterface, args []string) pb.Response

// 选择商品价格在1元到100元之间的商品名称和数量

s := "\\"fields\\": [\\"GoodsName\\", \\"GoodsCount\\"], \\"selector\\": \\"$and\\": [\\"GoodPrice\\":\\"$gte\\": 1, \\"GoodPrice\\":\\"$lte\\": 100] "

resultsIterator, err := stub.GetQueryResult(q)

defer resultsIterator.Close()

if err != nil

return shim.Error(err.Error())

var count uint64

for resultsIterator.HasNext()

count++

// resultsIterator.Next() // 注释掉该语句,函数将陷入死循环

fmt.Println("count=", count)

msg := fmt.Sprintf("count: %d", count)

return shim.Success([]byte(msg))

上面的代码由于把 resultsIterator.Next() 这行代码注释掉,返回的数据集如果包含有1条记录或以上,游标就会一直停留在第一条数据记录上,导致 resultsIterator.HasNext() 永远为true,从而陷入死循环。

合约函数陷入死循环后,由于Fabric一般默认的智能合约函数调用时长最长为30秒,超过30秒后,Fabric会返回类似于下面的超时提示:

Error: endorsement failure during invoke. response: status:500 message:"failed to execute transaction 81f3c7715ae5f6678c711238571bb1c778c274bc505287da3f857465835832d6: error sending: timeout expired while executing transaction"

你以为合约函数调用就这样结束了?No!如果你attach上peer节点(具体命令是:docker attach c5841e55155a,c5841e55155a为该节点的CONTAINER ID),你会发现,peer节点的log会不断地打印出类似下面的信息:

count= 10000

count= 10001

count= 10002

count= 10003

count= 10004

count= 10005

count= 10006

count= 10007

count= 10008

count= 10009

...

表明合约函数还在不断地执行死循环代码。

如果这时候,你想在客户端执行其它的合约函数,得到的结果都是超时,因为智能合约在上次调用中陷入死循环后,没办法执行新的函数调用了。后果真的很严重,需要认真注意合约函数会引起死循环的代码!

要如何结束死循环,目前来看只有重启peer节点了。如果你有更好的方法,欢迎提出来讨论。

------------------------------------------------------------------------------

我是powervip

我的公众号:区块链战斗机

我的知乎:powervip - 知乎

我的学习笔记:www.study.win

原创作品,版权所有,侵权必究!商业转载请联系作者获得授权;非商业转载需保留作者署名信息,注明出处并保留原文链接。

如果你觉得这篇文章写得还可以,请帮忙点个赞,谢谢!

你的鼓励,我的动力! 

C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)

上学期学习了汇编语言,并在操作系统实验中使用了汇编+C语言混合编程,中间也了解了一些C语言与汇编语言的对应关系。
由于汇编语言是底层的编程语言,各种函数参数都要直接控制栈进行存取,在混合编程中,要用汇编来调用C函数,当然就要知道参数的压栈情况了。
当知道C函数的参数压栈顺序是从右到左时,我觉得很奇怪,因为大多数情况下,人们的习惯是从左到右的,难不成设计者学咱们中国古代写字从右到左的习惯不成?
当时只是记下了这个规则而已,并没有去探究这其中的缘由,后来在实验中自己用汇编实现了printf和scanf函数的基本功能,尝到了压栈从右到左的好处,但是仍然没有多想。
直到前阵子看斯坦福大学公开课的时候,老师解释了一番才恍然大悟!
那么,这是为什么呢?
要回答这个问题,就不得不谈一谈printf()函数,printf函数的原型是:printf(const char* format,…)
没错,它是一个不定参函数,那么我们在实际使用中是怎么样知道它的参数个数呢?这就要靠format了,编译器通过format中的%占位符的个数来确定参数的个数。
现在我们假设参数的压栈顺序是从左到右的,这时,函数调用的时候,format最先进栈,之后是各个参数进栈,最后pc进栈,此时,由于format先进栈了,上面压着未知个数的参数,想要知道参数的个数,必须找到format,而要找到format,必须要知道参数的个数,这样就陷入了一个无法求解的死循环了!!
而如果把参数从右到左压栈,情况又是怎么样的?函数调用时,先把若干个参数都压入栈中,再压format,最后压pc,这样一来,栈顶指针加2便找到了format,通过format中的%占位符,取得后面参数的个数,从而正确取得所有参数。
所以,如果不存在…这种不定参的函数,则参数的压栈顺序无论是从左到右还是从右到左都是没关系的。

http://m.blog.csdn.net/article/details?id=47381597

以上是关于如果Fabric的智能合约函数陷入死循环会怎么样的主要内容,如果未能解决你的问题,请参考以下文章

【求解】为啥会陷入死循环?

Hyperledger Fabric 2.x 动态更新智能合约

fabric 智能合约开发详解

C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)

hyperledger fabric 智能合约开发

Hyperledger Fabric 智能合约实战 sdk node软件安装