Пример #1
0
static void
bbsluaHook(lua_State *L, lua_Debug* ar)
{
    // vmsg("bbslua HOOK!");
    if (blrt.abort)
    {
        vkey_purge();
        lua_yield(L, 0);
        return;
    }

    if (ar->event != LUA_HOOKCOUNT)
        return;
#ifdef BBSLUA_USAGE
    bbslua_count += BLCONF_EXEC_COUNT;
#endif

    // now, peek and check
    if (vkey_is_full())
        vkey_purge();

    // refresh();

    // check if input key is system break key.
    if (bl_peekbreak(BLCONF_PEEK_TIME))
    {
        lua_yield(L, 0);
        return;
    }
}
Пример #2
0
static int
qltcp_send(lua_State *state) {
  int                 nret, error;
  qsocket_t          *socket;
  qactor_t           *actor;
  qengine_t          *engine;

  socket = (qsocket_t*)lua_touserdata(state, 1);
  if (socket->state != QINET_STATE_CONNECTED) {
    lua_pushnil(state);
    lua_pushliteral(state, "socket not in connected state");
    return 2;
  }

  nret = qnet_tcp_send(socket, &error);
  if (nret < 0) {
    qevent_del(&socket->event, socket->event.events);
    qnet_close(socket->event.fd);
    lua_pushnil(state);
    lua_pushfstring(state, "send to %s error:%s",
                    socket->peer, strerror(error));
    return 2;
  }
  if (nret == 0) {
    actor = qlua_get_actor(state);
    engine = qactor_get_engine(actor->aid);
    socket->event.write = socket_send;
    qevent_add(engine, &socket->event, QEVENT_WRITE);
    actor->waiting_netio = 1;
    return lua_yield(state, 0); 
  }

  lua_pushnumber(state, nret);
  return 1;
}
Пример #3
0
int JLuaServer::FnWait( lua_State* pLua )
{
    if (lua_gettop( pLua ) != 1)
    {
        rlog.err( "LUA: Incorrect command usage: <wait>. "
            "Function takes 1 number argument, but %d is provided", lua_gettop( pLua ) );
        lua_settop( pLua, 0 );
        lua_pushnil( pLua );
        return lua_yield( pLua, 0 );
    }

    JLuaThread* pThread = reinterpret_cast<JLuaThread*>( pLua->userdata );
    assert( pThread->m_pLua == pLua );
    pThread->m_WaitTime += (double)lua_tonumber( pLua, -1 );
    return lua_yield( pLua, 0 );
} // JLuaServer::FnWait
Пример #4
0
void threading_yield_hook(lua_State *L, lua_Debug *ar) {
  if (ar->event & LUA_HOOKCOUNT) {
    lua_yield(L, 0);
  } else if (threading_old_hook != NULL) {
    (*threading_old_hook)(L, ar);
  }
}
Пример #5
0
static int __yield_end_of_frame ( lua_State *_l ) {
    if ( _l == ex_lua_main_state() )
        return luaL_error( _l, "the yield instruction only run in coroutine." );

    lua_pushnumber(_l,EX_YIELD_WAIT_FOR_END_OF_FRAME);
    return lua_yield(_l,2);
}
Пример #6
0
Файл: file.c Проект: halfd/lem
static int
file_seek(lua_State *T)
{
	static const int mode[] = { SEEK_SET, SEEK_CUR, SEEK_END };
	static const char *const modenames[] = { "set", "cur", "end", NULL };
	struct file *f;
	int op;
	lua_Number offset;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	op = luaL_checkoption(T, 2, "cur", modenames);
	offset = luaL_optnumber(T, 3, 0.);
	f = lua_touserdata(T, 1);
	f->seek.offset = (off_t)offset;
	luaL_argcheck(T, (lua_Number)f->seek.offset == offset, 3,
			"not an integer in proper range");
	if (f->fd < 0)
		return io_closed(T);
	if (f->T != NULL)
		return io_busy(T);

	/* flush input buffer */
	lem_inputbuf_init(&f->buf);

	f->T = T;
	f->seek.whence = mode[op];
	lem_async_do(&f->a, file_seek_work, file_seek_reap);

	lua_settop(T, 1);
	return lua_yield(T, 1);
}
Пример #7
0
Файл: file.c Проект: halfd/lem
static int
file_readp(lua_State *T)
{
	struct file *f;
	struct lem_parser *p;
	int ret;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	ret = lua_type(T, 2);
	if (ret != LUA_TUSERDATA && ret != LUA_TLIGHTUSERDATA)
		return luaL_argerror(T, 2, "expected userdata");

	f = lua_touserdata(T, 1);
	if (f->fd < 0)
		return io_closed(T);
	if (f->T != NULL)
		return io_busy(T);

	p = lua_touserdata(T, 2);
	if (p->init)
		p->init(T, &f->buf);

	ret = p->process(T, &f->buf);
	if (ret > 0)
		return ret;

	f->T = T;
	f->readp.p = p;
	lem_async_do(&f->a, file_readp_work, file_readp_reap);
	return lua_yield(T, lua_gettop(T));
}
Пример #8
0
int redis_lpush(lua_State *vm)
{
	char  *cmd;
	sds   str;
	int   len, argc, i;
	const char  *id, *key;

	argc  = lua_gettop(vm);
	argc += 1;
	id    = luaL_checkstring(vm, 1);
	str   = sdsnew("LPUSH");
	
	for(i=2; i<argc; i++)
	{
		key = luaL_checkstring(vm, i);
		str = sdscatprintf(str, " %s", key);
	}
	
	len = redisFormatCommand(&cmd, "%s", str);
	redis_pack_command(vm, id, cmd, len);
	zfree(cmd);
	sdsfree(str);
	cmd = NULL;
	
	return lua_yield(vm, 0);
}
Пример #9
0
static int
qlsleep(lua_State *state) {
  int         second;
  qactor_t   *actor;
  qengine_t  *engine;
  qid_t       id;
  qltimer_t  *timer;

  second = (int)lua_tonumber(state, 1);
  if (second <= 0) {
    lua_pushnil(state);
    lua_pushliteral(state, "wrong param");
    return 2;
  }

  timer = new_timer(NULL, NULL, NULL);
  if (timer == NULL) {
    lua_pushnil(state);
    lua_pushliteral(state, "create timer error");
    return 2;
  }

  actor = qlua_get_actor(state);
  engine = qactor_get_engine(actor->aid);
  id = qtimer_add(engine, second * 1000, timer_handler,
                  free_timer, 0, timer);
  timer->state = state;
  timer->id = id;
  timer->engine = engine;
  timer->actor = actor;
  qdict_set_numdata(actor->timers, id, timer, engine_free_timer);

  return lua_yield(state, 0);
}
Пример #10
0
Файл: utils.c Проект: esmil/lem
static int
utils_exit(lua_State *T)
{
	int status = (int)luaL_checknumber(T, 1);
	lem_exit(status);
	return lua_yield(T, 0);
}
Пример #11
0
int lua_echo(lua_State *L)
{
    epdata_t *epd = get_epd(L);

    if(!epd) {
        lua_pushnil(L);
        lua_pushstring(L, "miss epd!");
        return 2;
    }

    int nargs = lua_gettop(L);

    if(nargs < 1) {
        luaL_error(L, "miss content!");
        return 0;
    }

    size_t len = 0;

    if(epd->websocket) {
        return 0;
    }

    if(_lua_echo(epd, L, nargs, 1)) {
        return lua_yield(L, 0);
    }

    if(longtime() - epd->start_time > STEP_PROCESS_TIMEOUT) {
        epd->keepalive = 0;
        lua_pushstring(L, "Process Time Out!");
        lua_error(L);    /// stop lua script
    }

    return 0;
}
Пример #12
0
Файл: fs.c Проект: ifzz/LuaIO
/* local ret = fs.write(fd, data, pos)
 * ret < 0 => errno
 * ret >= 0 => write bytes
 */
static int LuaIO_fs_write(lua_State* L) {
  int fd = luaL_checkinteger(L, 1);
  /*common.h*/
  LuaIO_check_data(L, 2, fs_native:write(fd, data, pos));
  int pos = luaL_checkinteger(L, 3);

  CREATE_REQ1();
  req->bytes = bytes;
  int err = uv_fs_write(uv_default_loop(), 
                        &req->req,
                        fd,
                        bufs,
                        count,
                        pos,
                        LuaIO_fs_callback);
  if (err) {
    if(tmp != NULL) {
      LuaIO_pmemory_free(tmp);
    }

    LuaIO_pfree(&LuaIO_fs_req_pool, req);
    lua_pushinteger(L, err);
    return 1;
  }

  lua_pushvalue(L, 2);
  req->write_data_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  if(tmp != NULL) {
    LuaIO_pmemory_free(tmp);
  }

  return lua_yield(L, 0);
}
Пример #13
0
// actor:stop()
int ActorStop(lua_State *L) {
  // If we are executing, we are definitely not in any run queues. We will only
  // be in the global actor map. We just need to yield THREADING_EXITED and
  // we will be automagically destroyed by the scheduler.
  lua_pushinteger(L, THREADING_EXITED);
  return lua_yield(L, 1);
}
Пример #14
0
static int
db_exec(lua_State *T)
{
	struct db *db;
	const char *sql;
	size_t len;
	unsigned int bind;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	sql = luaL_checklstring(T, 2, &len);
	bind = lua_gettop(T) > 2;
	if (bind) {
		luaL_checktype(T, 3, LUA_TTABLE);
		lua_settop(T, 3);
		lua_replace(T, 2);
	}

	db = db_unbox(T, 1);
	if (db == NULL)
		return db_closed(T);
	if (db->T != NULL)
		return db_busy(T);

	db->T = T;
	db->req.prep.sql = sql;
	db->req.prep.len = len+1;
	lem_async_do(&db->a, db_prepare_work, db_exec_prepare_reap);

	return lua_yield(T, bind ? 2 : 1);
}
Пример #15
0
int quest_coroutine_yield(lua_State * L)
{
    CQuestManager& q = CQuestManager::instance();
    // other_pc_block 내부에서는 yield가 일어나서는 안된다. 절대로.
    if (q.IsInOtherPCBlock())
    {
        sys_err("FATAL ERROR! Yield occur in other_pc_block.");
        PC* pPC = q.GetOtherPCBlockRootPC();
        if (NULL == pPC)
        {
            sys_err("	... FFFAAATTTAAALLL Error. RootPC is NULL");
            return 0;
        }
        QuestState* pQS = pPC->GetRunningQuestState();
        if (NULL == pQS || NULL == q.GetQuestStateName(pPC->GetCurrentQuestName(), pQS->st))
        {
            sys_err("	... WHO AM I? WHERE AM I? I only know QuestName(%s)...", pPC->GetCurrentQuestName().c_str());
        }
        else
        {
            sys_err("	Current Quest(%s). State(%s)", pPC->GetCurrentQuestName().c_str(), q.GetQuestStateName(pPC->GetCurrentQuestName(), pQS->st));
        }
        return 0;
    }
    return lua_yield(L, lua_gettop(L));
}
Пример #16
0
int lua_f_coroutine_swop(lua_State *L)
{
    if(swop_counter++ < 800) {
        lua_pushboolean(L, 0);
        return 1;
    }

    cosocket_swop_t *swop = malloc(sizeof(cosocket_swop_t));

    if(swop == NULL) {
        lua_pushboolean(L, 0);
        return 1;
    }

    swop_counter = 0;
    swop->L = L;
    swop->next = NULL;

    if(swop_lat != NULL) {
        swop_lat->next = swop;

    } else {
        swop_top->next = swop;
    }

    swop_lat = swop;
    return lua_yield(L, 0);
}
Пример #17
0
static int
db_prepare(lua_State *T)
{
	struct db *db;
	const char *sql;
	size_t len;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	sql = luaL_checklstring(T, 2, &len);

	db = db_unbox(T, 1);
	if (db == NULL)
		return db_closed(T);
	if (db->T != NULL)
		return db_busy(T);

	db->T = T;
	db->refs++;
	db->req.prep.sql = sql;
	db->req.prep.len = len+1;
	lem_async_do(&db->a, db_prepare_work, db_prepare_reap);

	lua_settop(T, 2);
	lua_pushvalue(T, lua_upvalueindex(1));
	return lua_yield(T, 3);
}
Пример #18
0
Файл: server.c Проект: esmil/lem
static int
server_accept(lua_State *T)
{
	struct ev_io *w;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	w = lua_touserdata(T, 1);
	if (w->fd < 0)
		return io_closed(T);
	if (w->data != NULL)
		return io_busy(T);

	switch (server__accept(T, w, lua_upvalueindex(1))) {
	case 1:
		return 1;
	case 2:
		close(w->fd);
		w->fd= -1;
		return 2;
	}

	w->cb = server_accept_cb;
	w->data = T;
	ev_io_start(LEM_ w);
	lua_settop(T, 1);
	lua_pushvalue(T, lua_upvalueindex(1));
	return lua_yield(T, 2);
}
Пример #19
0
int wait( lua_State *L )
{
	// The lua state here is different from the main state, it's the thread created from the main state.
	long sec = (long)lua_tointeger( L, -1 );
	TimerManager::getSingleton().schedule( TIME_OUT_V( sec * 1000 ), 0, TimeOut, L );
	return lua_yield( L, 0 );
}
Пример #20
0
static int luaCB_md_detect_motion( lua_State* L )
{
    int columns = (luaL_optnumber(L,1,6));
    int rows = (luaL_optnumber(L,2,4));
    int pixel_measure_mode = (luaL_optnumber(L,3,1));
    int detection_timeout = (luaL_optnumber(L,4,10000));
    int measure_interval = (luaL_optnumber(L,5,7));
    int threshold = (luaL_optnumber(L,6,10));
    int draw_grid = (luaL_optnumber(L,7,1));
    // arg 8 is the return value in ubasic. We
    // ignore it here. - AUJ
    int clipping_region_mode = (luaL_optnumber(L,9,0));
    int clipping_region_column1 = (luaL_optnumber(L,10,0));
    int clipping_region_row1 = (luaL_optnumber(L,11,0));
    int clipping_region_column2 = (luaL_optnumber(L,12,0));
    int clipping_region_row2 = (luaL_optnumber(L,13,0));
    int parameters = (luaL_optnumber(L,14,1));
    int pixels_step = (luaL_optnumber(L,15,6));
    int msecs_before_trigger = (luaL_optnumber(L,16,0));
    if(md_init_motion_detector(
                columns, rows, pixel_measure_mode, detection_timeout,
                measure_interval, threshold, draw_grid,
                clipping_region_mode,
                clipping_region_column1, clipping_region_row1,
                clipping_region_column2, clipping_region_row2,
                parameters, pixels_step, msecs_before_trigger
            ))
        return lua_yield(L, 0);
    else
        return luaL_error( L, "md_init_motion_detector failed" );
}
Пример #21
0
int lua_read_request_body(lua_State *L)
{
    epdata_t *epd = get_epd(L);

    if(!epd) {
        lua_pushnil(L);
        lua_pushstring(L, "miss epd!");
        return 2;
    }

    if(epd->websocket) {
        return 0;
    }

    if(epd->contents) {
        epd->contents = NULL;

        lua_pushlstring(L, epd->headers + epd->_header_length, epd->data_len - epd->_header_length);
        return 1;
    }

    if(!epd->se_ptr || epd->content_length <= epd->data_len - epd->_header_length) {
        lua_pushnil(L);
        lua_pushstring(L, "eof");
        return 2;
    }

    epd->status = STEP_READ;
    serv_status.reading_counts++;
    se_be_read(epd->se_ptr, network_be_read_request_body);

    return lua_yield(L, 0);
}
Пример #22
0
/*
status = write_usb_msg(msg,[timeout])
writes a message to the CHDK ptp interface
msg may be nil, boolean, number, string or table (table has some restrictions, will be converted to string)
returns true if the message was queued successfully, otherwise false
if timeout is set and not zero, wait until message is written or timeout expires
NOTE strings will not include a terminating NULL, must be handled by recipient
*/
static int luaCB_write_usb_msg( lua_State* L )
{
    ptp_script_msg *msg;
    int timeout = luaL_optnumber( L, 2, 0 );
    // TODO would it be better to either ignore this or return nil ?
    // a write_usb_msg(function_which_returns_no_value()) is an error in this case
    // replacing with nil might be more luaish
    if(lua_gettop(L) < 1) {
        return luaL_error(L,"missing argument");
    }
    msg=lua_create_usb_msg(L,1,PTP_CHDK_S_MSGTYPE_USER);
    // for user messages, trying to create a message from an incompatible type throws an error
    if(msg->subtype == PTP_CHDK_TYPE_UNSUPPORTED) {
        free(msg);
        return luaL_error(L,"unsupported type");
    }
    if(!msg) {
        return luaL_error(L,"failed to create message");
    }
    if(timeout) {
        action_push(timeout);
        action_push((int)msg);
        action_push(AS_SCRIPT_WRITE_USB_MSG);
        return lua_yield( L, 0 );
    }
    lua_pushboolean(L,ptp_script_write_msg(msg));
    return 1;
}
Пример #23
0
int lua_flush(lua_State *L)
{
    epdata_t *epd = get_epd(L);

    if(!epd) {
        return 0;
    }

    int nargs = lua_gettop(L);
    _lua_echo(epd, L, nargs, 0);

    if(epd->status != STEP_PROCESS) {
        return 0;
    }

    if(epd->websocket || epd->status == STEP_SEND) {
        return 0;
    }

    if(network_flush(epd) == 1) {
        return lua_yield(L, 0);
    }

    return 0;
}
Пример #24
0
static int
ts_lua_sleep(lua_State *L)
{
  int sec;
  TSAction action;
  TSCont contp;
  ts_lua_async_item *ai;
  ts_lua_cont_info *ci;

  ci = ts_lua_get_cont_info(L);
  if (ci == NULL)
    return 0;

  sec = luaL_checknumber(L, 1);
  if (sec < 1) {
    sec = 1;
  }

  contp = TSContCreate(ts_lua_sleep_handler, ci->mutex);
  action = TSContSchedule(contp, sec * 1000, TS_THREAD_POOL_DEFAULT);

  ai = ts_lua_async_create_item(contp, ts_lua_sleep_cleanup, (void *)action, ci);
  TSContDataSet(contp, ai);

  return lua_yield(L, 0);
}
Пример #25
0
Файл: server.c Проект: esmil/lem
static int
server_autospawn(lua_State *T)
{
	struct ev_io *w;

	luaL_checktype(T, 1, LUA_TUSERDATA);
	luaL_checktype(T, 2, LUA_TFUNCTION);

	w = lua_touserdata(T, 1);
	if (w->fd < 0)
		return io_closed(T);
	if (w->data != NULL)
		return io_busy(T);

	w->cb = server_autospawn_cb;
	w->data = T;
	ev_io_start(LEM_ w);

	lem_debug("yielding");

	/* yield server object, function and metatable*/
	lua_settop(T, 2);
	lua_pushvalue(T, lua_upvalueindex(1));
	return lua_yield(T, 3);
}
Пример #26
0
int _lua_sleep(lua_State *L, int msec)
{
    sleep_timeout_t *n = malloc(sizeof(sleep_timeout_t));

    if(!n) {
        return 0;
    }

    n->timeout = (longtime() + msec) / 10;
    n->uper = NULL;
    n->next = NULL;
    n->L = L;

    int k = n->timeout % TIME_BUCKET_SIZE;

    if(timeout_link_ends[k] == NULL) {
        timeout_links[k] = n;
        timeout_link_ends[k] = n;

    } else { // add to link end
        timeout_link_ends[k]->next = n;
        n->uper = timeout_link_ends[k];
        timeout_link_ends[k] = n;
    }

    return lua_yield(L, 0);
}
static int
ngx_http_lua_ngx_sleep(lua_State *L)
{
    int                          n;
    ngx_int_t                    delay; /* in msec */
    ngx_http_request_t          *r;
    ngx_http_lua_ctx_t          *ctx;
    ngx_http_lua_co_ctx_t       *coctx;

    n = lua_gettop(L);
    if (n != 1) {
        return luaL_error(L, "attempt to pass %d arguments, but accepted 1", n);
    }

    r = ngx_http_lua_get_req(L);
    if (r == NULL) {
        return luaL_error(L, "no request found");
    }

    delay = (ngx_int_t) (luaL_checknumber(L, 1) * 1000);

    if (delay < 0) {
        return luaL_error(L, "invalid sleep duration \"%d\"", delay);
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
    if (ctx == NULL) {
        return luaL_error(L, "no request ctx found");
    }

    ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
                               | NGX_HTTP_LUA_CONTEXT_ACCESS
                               | NGX_HTTP_LUA_CONTEXT_CONTENT
                               | NGX_HTTP_LUA_CONTEXT_TIMER);

    coctx = ctx->cur_co_ctx;
    if (coctx == NULL) {
        return luaL_error(L, "no co ctx found");
    }

    coctx->data = r;

    coctx->sleep.handler = ngx_http_lua_sleep_handler;
    coctx->sleep.data = coctx;
    coctx->sleep.log = r->connection->log;

    dd("adding timer with delay %lu ms, r:%.*s", (unsigned long) delay,
       (int) r->uri.len, r->uri.data);

    ngx_add_timer(&coctx->sleep, (ngx_msec_t) delay);

    ngx_http_lua_cleanup_pending_operation(coctx);
    coctx->cleanup = ngx_http_lua_sleep_cleanup;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "lua ready to sleep for %d ms", delay);

    return lua_yield(L, 0);
}
static int
ngx_stream_lua_uthread_spawn(lua_State *L)
{
    int                             n;
    ngx_stream_session_t           *s;
    ngx_stream_lua_ctx_t           *ctx;
    ngx_stream_lua_co_ctx_t        *coctx = NULL;

    n = lua_gettop(L);

    s = ngx_stream_lua_get_session(L);
    if (s == NULL) {
        return luaL_error(L, "no session found");
    }

    ctx = ngx_stream_get_module_ctx(s, ngx_stream_lua_module);
    if (ctx == NULL) {
        return luaL_error(L, "no session ctx found");
    }

    ngx_stream_lua_coroutine_create_helper(L, s, ctx, &coctx);

    /* anchor the newly created coroutine into the Lua registry */

    lua_pushlightuserdata(L, &ngx_stream_lua_coroutines_key);
    lua_rawget(L, LUA_REGISTRYINDEX);
    lua_pushvalue(L, -2);
    coctx->co_ref = luaL_ref(L, -2);
    lua_pop(L, 1);

    if (n > 1) {
        lua_replace(L, 1);
        lua_xmove(L, coctx->co, n - 1);
    }

    coctx->is_uthread = 1;
    ctx->uthreads++;

    coctx->co_status = NGX_STREAM_LUA_CO_RUNNING;
    ctx->co_op = NGX_STREAM_LUA_USER_THREAD_RESUME;

    ctx->cur_co_ctx->thread_spawn_yielded = 1;

    if (ngx_stream_lua_post_thread(s, ctx, ctx->cur_co_ctx) != NGX_OK) {
        return luaL_error(L, "no memory");
    }

    coctx->parent_co_ctx = ctx->cur_co_ctx;
    ctx->cur_co_ctx = coctx;

#if 0
    /* TODO */
    ngx_stream_lua_probe_user_thread_spawn(s, L, coctx->co);
#endif

    dd("yielding with arg %s, top=%d, index-1:%s", luaL_typename(L, -1),
       (int) lua_gettop(L), luaL_typename(L, 1));
    return lua_yield(L, 1);
}
Пример #29
0
int task_yield(task_id tid) {
  task_t *t = task_ref(tid);
  if (!t) return ERR_INVAL;
  lua_State *L = t->L;
  task_free(tid);
  //task_resume(tid,m);
  return lua_yield(L,0);
}
Пример #30
0
static int tcp_write(lua_State *l)
{
    tcp_udata_t *udata  = connection_udata(l);
    ls_tcp_t    *tcp    = udata->handle;
    uv_stream_t *handle = (uv_stream_t *)&tcp->handle;
    uv_buf_t     bufs[MAX_WRITE_BUF_COUNT];
    int          refs[MAX_WRITE_BUF_COUNT];
    int          datacnt;
    int          i;
    ls_write_t   *write_req;

    if (tcp == NULL)
        return ls_error_return(l, LS_ERRCODE_EOF, "tcp connection closed.");

    datacnt = lua_gettop(l) - 1;

    if (datacnt > arraysize(bufs))
        return ls_error_return(l, LS_ERRCODE_ARGSIZE, "too much data to write.");
    else if (datacnt <= 0)
    {
        lua_pushboolean(l, 1);
        return 1;
    }

    for (i=0; i<datacnt; i++)
    {
        size_t len;
        const char *data = lua_tolstring(l, i+2, &len);
        if (data == NULL)
            return ls_error_return(l, LS_ERRCODE_INVAL, "invalid data to be writen: should be string or number");
        bufs[i] = uv_buf_init((char*)data, len);
    }

    // now, number in the stack has already been converted into string

    write_req = new_write_req(l);

    
    if (uv_write(&write_req->req, handle, bufs, datacnt, tcp_write_cb))
    {
        ls_free(l, write_req);
        return ls_last_error_return(l, handle->loop);
    }

    // make ref to the string
    for (i=0; i<datacnt; i++)
    {
        write_req->data_refs[i] = ls_ref_value(l, i+2);
    }

    write_req->refcnt = datacnt;

    // libuv make sure now tcp_write_cb is not called, even the data
    // has been writen already.
    ls_set_waiting(l, &write_req->wait_object, udata->timeout);

    return lua_yield(l, 0);
}