示例#1
0
文件: visual_io.c 项目: callcc/tekui
static void tek_lib_visual_io_task(struct TTask *task)
{
	struct TExecBase *TExecBase = TGetExecBase(task);
	struct IOData *iodata = TGetTaskData(task);
	TEKVisual *vis = iodata->vis;
	TIMSG *imsg;
	TUINT sig;
	#if defined(ENABLE_FILENO) || defined(ENABLE_DGRAM)
	char buf[256];
	fd_set rset;
	#endif
	do
	{
		#if defined(ENABLE_FILENO) || defined(ENABLE_DGRAM)
		FD_ZERO(&rset);
		FD_SET(iodata->fd_pipe[0], &rset);
		#endif
		#if defined(ENABLE_FILENO)
		if (iodata->fd_stdin != -1)
			FD_SET(iodata->fd_stdin, &rset);
		#endif
		#if defined(ENABLE_DGRAM)
		FD_SET(iodata->fd_dgram, &rset);
		#endif
		#if defined(ENABLE_FILENO) || defined(ENABLE_DGRAM)
		if (select(iodata->fdmax, &rset, NULL, NULL, NULL) > 0)
		{
			int nbytes = 0;
			
			/* consume signal: */
			if (FD_ISSET(iodata->fd_pipe[0], &rset))
			{
				ioctl(iodata->fd_pipe[0], FIONREAD, &nbytes);
				if (nbytes > 0)
					if (read(iodata->fd_pipe[0], buf,
						TMIN(sizeof(buf), (size_t) nbytes)) != nbytes)
					TDBPRINTF(TDB_ERROR,("Error reading from selfpipe\n"));
			}
			
			#if defined(ENABLE_FILENO)
			/* stdin line reader: */
			if (iodata->fd_stdin >= 0 && FD_ISSET(iodata->fd_stdin, &rset))
			{
				if (ioctl(iodata->fd_stdin, FIONREAD, &nbytes) == 0)
				{
					if (nbytes == 0)
						iodata->fd_stdin = -1; /* stop processing */
					else
					{
						char *line;
						size_t len;
						visual_io_reader_addbytes(&iodata->linereader, nbytes);
						while (visual_io_readline(&iodata->linereader, &line,
							&len))
						{
							if (getusermsg(vis, &imsg, TITYPE_USER, len))
							{
								memcpy((void *) (imsg + 1), line, len);
								TPutMsg(vis->vis_IMsgPort, TNULL,
									&imsg->timsg_Node);
							}
						}
					}
				}
				else
					iodata->fd_stdin = -1; /* stop processing */
			}
			#endif
			
			#if defined(ENABLE_DGRAM)
			if (iodata->fd_dgram >= 0 && FD_ISSET(iodata->fd_dgram, &rset))
			{
				char umsg[IOMAXMSGSIZE];
				TIMSG *imsg;
				ssize_t len = recv(iodata->fd_dgram, umsg, sizeof umsg, 0);
				if (len >= 0 && getusermsg(vis, &imsg, TITYPE_USER, len))
				{
					memcpy((void *) (imsg + 1), umsg, len);
					TPutMsg(vis->vis_IMsgPort, TNULL, &imsg->timsg_Node);
				}
			}
			#endif
		}
		sig = TSetSignal(0, TTASK_SIG_ABORT | TTASK_SIG_USER);
		#else
		sig = TWait(TTASK_SIG_ABORT | TTASK_SIG_USER);
		#endif
		if (sig & TTASK_SIG_USER)
		{
			TAPTR msg, uport = TGetUserPort(TNULL);
			while ((msg = TGetMsg(uport)))
			{
				TSIZE len = TGetSize(msg);
				/* repackage into user input message */
				if (getusermsg(vis, &imsg, TITYPE_USER, len))
				{
					memcpy((void *) (imsg + 1), msg, len);
					TPutMsg(vis->vis_IMsgPort, TNULL, &imsg->timsg_Node);
				}
				TAckMsg(msg);
			}
		}
	} while (!(sig & TTASK_SIG_ABORT));
	
	tek_lib_visual_io_exit(task);
}
示例#2
0
static int tek_lib_exec_child_sigjoin(lua_State *L, TUINT sig, TBOOL sigparent,
	TBOOL do_results)
{
	struct LuaExecChild *ctx = luaL_checkudata(L, 1, TEK_LIB_TASK_CLASSNAME);
	struct TExecBase *TExecBase = ctx->exec;
	struct TTask *self = TFindTask(TNULL), *task = ctx->task;
	union TTaskRequest *req = &self->tsk_Request;
	TBOOL abort = TFALSE;
	int nres = 0;
	if (!task)
		return 0;
	
	TDBPRINTF(TDB_TRACE,("child_join sig=%d sigparent=%d\n", sig, sigparent));
	
	/* signal task */
	TSignal(task, sig);
	/* prepare destroy request */
	self->tsk_ReqCode = TTREQ_DESTROYTASK;
	req->trq_Task.trt_Task = task;
	/* send to exec */
	TPutMsg(TExecBase->texb_ExecPort, &self->tsk_SyncPort, self);
	for (;;)
	{
		/* wait for return of request or receiving abort ourselves: */
		TUINT sig = TWait(TTASK_SIG_SINGLE | TTASK_SIG_ABORT);
		if (sig & TTASK_SIG_SINGLE)
			break;
		if (sig & TTASK_SIG_ABORT)
		{
			/* forward to child task */
			TSignal(task, TTASK_SIG_ABORT);
			if (sigparent)
			{
				/* also forward to own parent task */
				struct LuaExecTask *parent = getparent(TExecBase);
				if (parent)
					TSignal(parent->task, TTASK_SIG_ABORT);
				abort = TTRUE;
			}
		}
	}
	/* take delivery of replied destroy request */
	TGetMsg(&self->tsk_SyncPort);
	/* free task */	
	TFreeTask(task);
	
	ctx->task = TNULL;
	tek_lib_exec_freectxargs(ctx);
	if (!abort && do_results)
	{
		int i;
		nres = ctx->numres + 1;
		lua_pushboolean(L, ctx->luastatus == 0);
		for (i = 0; i < ctx->numres; ++i)
			lua_pushlstring(L, ctx->results[i].arg, ctx->results[i].len);
	}
	tek_lib_exec_freeargs(TExecBase, ctx->results, ctx->numres);
	luaL_unref(L, lua_upvalueindex(1), ctx->ref);
	if (abort)
		luaL_error(L, "received abort signal");
	return nres;
}