diff options
author | Jimmy Hu <jimmy.hu@dexon.org> | 2018-12-04 14:54:28 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@dexon.org> | 2019-04-09 21:32:54 +0800 |
commit | 6de8d29263b2c184ddd0506d05a18d33554d9788 (patch) | |
tree | e2422fa3bac698e6232dcad4f4434d06aad5f559 /dex | |
parent | 114a67a1e4f70e186617b01e766fb49793b73b60 (diff) | |
download | dexon-6de8d29263b2c184ddd0506d05a18d33554d9788.tar dexon-6de8d29263b2c184ddd0506d05a18d33554d9788.tar.gz dexon-6de8d29263b2c184ddd0506d05a18d33554d9788.tar.bz2 dexon-6de8d29263b2c184ddd0506d05a18d33554d9788.tar.lz dexon-6de8d29263b2c184ddd0506d05a18d33554d9788.tar.xz dexon-6de8d29263b2c184ddd0506d05a18d33554d9788.tar.zst dexon-6de8d29263b2c184ddd0506d05a18d33554d9788.zip |
core, dex: Timeout for prepare payload (#72)
* Timeout on prepare payload
* Leave 2 CPU for others
* Add hardLimit and softLimit to PreparePayload
Diffstat (limited to 'dex')
-rw-r--r-- | dex/app.go | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/dex/app.go b/dex/app.go index cf36ad816..eae9ba0b3 100644 --- a/dex/app.go +++ b/dex/app.go @@ -18,6 +18,7 @@ package dex import ( + "context" "fmt" "math/big" "sync" @@ -129,8 +130,54 @@ func (d *DexconApp) validateNonce(txs types.Transactions) (map[common.Address]ui // PreparePayload is called when consensus core is preparing payload for block. func (d *DexconApp) PreparePayload(position coreTypes.Position) (payload []byte, err error) { + // softLimit limits the runtime of inner call to preparePayload. + // hardLimit limits the runtime of outer PreparePayload. + // If hardLimit is hit, it is possible that no payload is prepared. + softLimit := 100 * time.Millisecond + hardLimit := 150 * time.Millisecond + ctx, cancel := context.WithTimeout(context.Background(), hardLimit) + defer cancel() + payloadCh := make(chan []byte, 1) + errCh := make(chan error, 1) + doneCh := make(chan struct{}, 1) + go func() { + ctx, cancel := context.WithTimeout(context.Background(), softLimit) + defer cancel() + payload, err := d.preparePayload(ctx, position) + if err != nil { + errCh <- err + } + payloadCh <- payload + doneCh <- struct{}{} + }() + select { + case <-ctx.Done(): + case <-doneCh: + } + select { + case err = <-errCh: + if err != nil { + return + } + default: + } + select { + case payload = <-payloadCh: + default: + } + return +} + +func (d *DexconApp) preparePayload(ctx context.Context, position coreTypes.Position) ( + payload []byte, err error) { d.chainRLock(position.ChainID) defer d.chainRUnlock(position.ChainID) + select { + // This case will hit if previous RLock took too much time. + case <-ctx.Done(): + return + default: + } if position.Height != 0 { // Check if chain block height is strictly increamental. @@ -171,6 +218,11 @@ func (d *DexconApp) PreparePayload(position coreTypes.Position) (payload []byte, addressMap: for address, txs := range txsMap { + select { + case <-ctx.Done(): + break addressMap + default: + } // TX hash need to be slot to the given chain in order to be included in the block. if !d.addrBelongsToChain(address, chainNums, chainID) { continue @@ -332,6 +384,9 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta } var transactions types.Transactions + if len(block.Payload) == 0 { + return coreTypes.VerifyOK + } err = rlp.DecodeBytes(block.Payload, &transactions) if err != nil { log.Error("Payload rlp decode", "error", err) |