github.com/igggame/nebulas-go@v2.1.0+incompatible/nf/nvm/v8/thread_engine.cc (about)

     1  // Copyright (C) 2017 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or
     6  // modify it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see
    17  // <http://www.gnu.org/licenses/>.
    18  //
    19  
    20  #include "engine.h"
    21  #include "engine_int.h"
    22  #include "lib/tracing.h"
    23  #include "lib/typescript.h"
    24  #include "lib/logger.h"
    25  #include "lib/nvm_error.h"
    26  
    27  #include <assert.h>
    28  #include <string.h>
    29  #include <stdio.h>
    30  // #include <stdlib.h>
    31  #include <stdlib.h>
    32  #include <thread>
    33  #include <sys/time.h>
    34  #include <unistd.h>
    35  #define MicroSecondDiff(newtv, oldtv) (1000000 * (unsigned long long)((newtv).tv_sec - (oldtv).tv_sec) + (newtv).tv_usec - (oldtv).tv_usec)  //微秒
    36  #define CodeExecuteErr 1
    37  #define CodeExecuteInnerNvmErr 2
    38  #define CodeTimeOut    3
    39  
    40  void SetRunScriptArgs(v8ThreadContext *ctx, V8Engine *e, int opt, const char *source, int line_offset, int allow_usage) {
    41    ctx->e = e;
    42    ctx->input.source = source;
    43    ctx->input.opt = (OptType)opt;
    44    ctx->input.allow_usage = allow_usage;
    45    ctx->input.line_offset = line_offset;
    46  }
    47  
    48  char *InjectTracingInstructionsThread(V8Engine *e, const char *source,
    49                                  int *source_line_offset,
    50                                  int allow_usage) {
    51    v8ThreadContext ctx;
    52    memset(&ctx, 0x00, sizeof(ctx));
    53    SetRunScriptArgs(&ctx, e, INSTRUCTION, source, *source_line_offset, allow_usage);
    54  	bool btn = CreateScriptThread(&ctx);
    55    if (btn == false) {
    56      LogErrorf("Failed to create script thread");
    57      return NULL;
    58    }
    59    *source_line_offset = ctx.output.line_offset;
    60    return ctx.output.result;
    61  }
    62  
    63  char *TranspileTypeScriptModuleThread(V8Engine *e, const char *source,
    64                                  int *source_line_offset) {
    65    v8ThreadContext ctx;
    66    memset(&ctx, 0x00, sizeof(ctx));
    67    SetRunScriptArgs(&ctx, e, INSTRUCTIONTS, source, *source_line_offset, 1);
    68  	bool btn = CreateScriptThread(&ctx);
    69    if (btn == false) {
    70      return NULL;
    71    }
    72    *source_line_offset = ctx.output.line_offset;
    73    return ctx.output.result;
    74  }
    75  int RunScriptSourceThread(char **result, V8Engine *e, const char *source,
    76                      int source_line_offset, uintptr_t lcs_handler,
    77                      uintptr_t gcs_handler) {
    78    v8ThreadContext ctx;
    79    memset(&ctx, 0x00, sizeof(ctx));
    80    SetRunScriptArgs(&ctx, e, RUNSCRIPT, source, source_line_offset, 1);
    81  	ctx.input.lcs = lcs_handler;
    82    ctx.input.gcs = gcs_handler;  
    83  
    84    bool btn = CreateScriptThread(&ctx);
    85    if (btn == false) {
    86      return NVM_UNEXPECTED_ERR;
    87    }
    88  
    89    *result = ctx.output.result;
    90    return ctx.output.ret;
    91  }
    92  
    93  void *ExecuteThread(void *args) {
    94    v8ThreadContext *ctx = (v8ThreadContext*)args;
    95    if (ctx->input.opt == INSTRUCTION) {
    96      TracingContext tContext;
    97      tContext.source_line_offset = 0;
    98      tContext.tracable_source = NULL;
    99      tContext.strictDisallowUsage = ctx->input.allow_usage;
   100  
   101      Execute(NULL, ctx->e, ctx->input.source, 0, 0L, 0L, InjectTracingInstructionDelegate,
   102              (void *)&tContext);
   103  
   104      ctx->output.line_offset = tContext.source_line_offset;
   105      ctx->output.result = static_cast<char *>(tContext.tracable_source);
   106    } else if (ctx->input.opt == INSTRUCTIONTS) {
   107      TypeScriptContext tContext;
   108      tContext.source_line_offset = 0;
   109      tContext.js_source = NULL;
   110  
   111      Execute(NULL, ctx->e, ctx->input.source, 0, 0L, 0L, TypeScriptTranspileDelegate,
   112              (void *)&tContext);
   113  
   114      ctx->output.line_offset = tContext.source_line_offset;
   115      ctx->output.result = static_cast<char *>(tContext.js_source);
   116    } else {
   117      ctx->output.ret = Execute(&ctx->output.result, ctx->e, ctx->input.source, ctx->input.line_offset, (void *)ctx->input.lcs,
   118                  (void *)ctx->input.gcs, ExecuteSourceDataDelegate, NULL);
   119      // printf("iRtn:%d--result:%s\n", ctx->output.ret, ctx->output.result);
   120    }
   121  
   122    ctx->is_finished = true;
   123    return 0x00;
   124  }
   125  // return : success return true. if hava err ,then return false. and not need to free heap
   126  // if gettimeofday hava err ,There is a risk of an infinite loop
   127  bool CreateScriptThread(v8ThreadContext *ctx) {
   128    pthread_t thread;
   129    pthread_attr_t attribute;
   130    pthread_attr_init(&attribute);
   131    pthread_attr_setstacksize(&attribute, 2 * 1024 * 1024);
   132    pthread_attr_setdetachstate (&attribute, PTHREAD_CREATE_DETACHED);
   133    struct timeval tcBegin, tcEnd;
   134    int rtn = gettimeofday(&tcBegin, NULL);
   135    if (rtn != 0) {
   136      LogErrorf("CreateScriptThread get start time err:%d\n", rtn);
   137      return false;
   138    }
   139    rtn = pthread_create(&thread, &attribute, ExecuteThread, (void *)ctx);
   140    if (rtn != 0) {
   141      LogErrorf("CreateScriptThread pthread_create err:%d\n", rtn);
   142      return false;
   143    }
   144    
   145    int timeout = ctx->e->timeout;
   146    bool is_kill = false;
   147    //thread safe
   148    while(1) {
   149      if (ctx->is_finished == true) {
   150          if (is_kill == true) {
   151            ctx->output.ret = NVM_EXE_TIMEOUT_ERR; 
   152            // ctx->output.ret = CodeTimeOut; 
   153          } 
   154          else if (ctx->e->is_inner_nvm_error_happen == 1) {
   155            ctx->output.ret = NVM_INNER_EXE_ERR;
   156          }
   157          break;
   158      } else {
   159        usleep(10); //10 micro second loop .epoll_wait optimize
   160        rtn = gettimeofday(&tcEnd, NULL);
   161        if (rtn) {
   162          LogErrorf("CreateScriptThread get end time err:%d\n", rtn);
   163          continue;
   164        }
   165        int diff = MicroSecondDiff(tcEnd, tcBegin);
   166    
   167        if (diff >= timeout && is_kill == false) { 
   168          LogErrorf("CreateScriptThread timeout timeout:%d diff:%d\n", timeout, diff);
   169          TerminateExecution(ctx->e);
   170          is_kill = true;
   171        }
   172      }
   173    }
   174    return true;
   175  }