Ejemplo n.º 1
0
static void *tea_thread(void *data)
{
  int r;
  THREAD_WORK *tw = (THREAD_WORK *) data;

  /* initialize thread */
  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &r);
  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &r);
  pthread_cleanup_push((void *) tea_thread_cleanup, tw);

  /* launch thread */
  TDBG("[tea-thread] Starting thread main function");
  tw->to->thread(tw);
  TDBG("[tea-thread] Thread main function finished.");

  /* wait until the correct die moment */
  TDBG2("[tea-thread] Waiting for cleanup approval...");
  while( pthreadex_flag_wait_timeout(&(tw->cleanup_do), 1000))
  {
    TDBG2("[tea-thread]  ...");
  }

  /* finish him */
  pthread_cleanup_pop(1);
  pthread_exit(NULL);

  return NULL;
}
Ejemplo n.º 2
0
static void tea_thread_cleanup(THREAD_WORK *tw)
{
  TEA_MSG_QUEUE *mq;

  /* do thread cleanup */
  TDBG2("[tea-cleanup] Thread final cleanup started.");
  if(tw->to->cleanup)
    tw->to->cleanup(tw);

  if(tw->data != NULL)
  {
    free(tw->data);
    tw->data = NULL;
  }

  /* disassociate mqueue of tw and destroy it */
  if(tw->to->listener || tw->to->sender)
  {
    pthreadex_mutex_begin(&(tw->mqueue->mutex));
    TDBG2("[tea-cleanup] listener/sender cleanup");
    mq = tw->mqueue;
    tw->mqueue = NULL;
    pthreadex_mutex_end();

    if(mq)
    {
      TDBG2("[tea-cleanup] mqueue cleanup");
      mqueue_destroy(mq);
    }
  }

  TDBG("[tea-cleanup] Thread finished.");
  pthreadex_flag_up(&(tw->cleanup_done));
}
Ejemplo n.º 3
0
/*
 * Execute elements.
 */
enum exec_rtn
_tmpl_execute_elems(struct tmpl_ctx *ctx,
	struct tmpl_elem *const elems, int first_elem, int nelems)
{
#if TMPL_DEBUG
	char indent[80];
#endif
	enum exec_rtn rtn;
	int i;

	/* Increase nesting */
	ctx->depth++;

	/* Check for infinite loop */
	if (ctx->depth >= INFINITE_LOOP) {
		pr_err(ctx, 0, "too much recursion in template execution");
		rtn = RTN_NORMAL;
		goto done;
	}

	/* Debug */
#if TMPL_DEBUG
	*indent = '\0';
	for (i = 1; i < ctx->depth; i++)
		strlcat(indent, "  ", sizeof(indent));
	TDBG("%sExecuting %d elems starting at %d\n",
	    indent _ nelems _ first_elem);
#endif

	/* Execute elements in order */
	for (i = first_elem; i < first_elem + nelems; i++) {
		struct tmpl_elem *const elem = &elems[i];

		TDBG("%s%4d: %s\n", indent _ i _ _tmpl_elemstr(&elems[i] _ i));

		/* Handle normal text */
		if (elem->text != NULL) {

			/* Optionally skip initial NL + whitespace */
			if (((elem->flags & TMPL_ELEM_NL_WHITE) != 0
			    && ctx->flags & TMPL_SKIP_NL_WHITE) != 0)
				continue;

			/* Output text */
			fwrite(elem->text, 1, elem->len, ctx->output);
			continue;
		}

		/* Handle function call */
		switch (elem->call.type) {
		case TY_NORMAL:
		    {
			char *errmsg = NULL;
			char *result;

			if ((result = _tmpl_invoke(ctx,
			    &errmsg, &elem->call)) == NULL) {
				pr_err(ctx, errno, errmsg);
				FREE(ctx->mtype, errmsg);
				break;
			}
			TDBG("%s      --> \"%s\"\n", indent _ result);
			(void)fputs(result, ctx->output);
			FREE(ctx->mtype, result);
			break;
		    }

		case TY_LOOP:
		    {
			struct loop_ctx this;
			char *errmsg = NULL;
			long count;
			char *eptr;
			char *x;

			if (!(x = evaluate_arg(ctx,
			    &errmsg, &elem->call.args[0]))) {
				pr_err(ctx, errno, errmsg);
				FREE(ctx->mtype, errmsg);
				i += elem->u.u_loop.endloop;
				break;
			}
			count = strtoul(x, &eptr, 10);
			if (*x == '\0' || *eptr != '\0'
			    || count < 0 || count == LONG_MAX) {
				char buf[32];

				snprintf(buf, sizeof(buf),
				    "invalid loop count \"%s\"", x);
				pr_err(ctx, 0, buf);
				FREE(ctx->mtype, x);
				i += elem->u.u_loop.endloop;
				break;
			}
			FREE(ctx->mtype, x);
			this.outer = ctx->loop;
			ctx->loop = &this;
			for (this.index = 0; this.index < count; this.index++) {
				rtn = _tmpl_execute_elems(ctx, elems,
				    i + 1, elem->u.u_loop.endloop - 1);
				if (rtn == RTN_BREAK)
					break;
				if (rtn == RTN_RETURN) {
					ctx->loop = this.outer;
					goto done;
				}
			}
			ctx->loop = this.outer;
			i += elem->u.u_loop.endloop;
			break;
		    }

		case TY_WHILE:
			while (1) {
				char *errmsg = NULL;
				int truth;
				char *x;

				if (!(x = evaluate_arg(ctx,
				    &errmsg, &elem->call.args[0]))) {
					pr_err(ctx, errno, errmsg);
					FREE(ctx->mtype, errmsg);
					i += elem->u.u_while.endwhile;
					break;
				}
				truth = _tmpl_true(x);
				FREE(ctx->mtype, x);
				if (!truth)
					break;
				rtn = _tmpl_execute_elems(ctx, elems, i + 1,
				    elem->u.u_while.endwhile - 1);
				if (rtn == RTN_BREAK)
					break;
				if (rtn == RTN_RETURN)
					goto done;
			}
			i += elem->u.u_while.endwhile;
			break;

		case TY_IF:
		case TY_ELIF:
		    {
			char *errmsg = NULL;
			int first = -1;
			int num = 0;
			int truth;
			char *x;

			if (!(x = evaluate_arg(ctx,
			    &errmsg, &elem->call.args[0]))) {
				pr_err(ctx, errno, errmsg);
				FREE(ctx->mtype, errmsg);
				i += elem->u.u_if.endif;
				break;
			}
			truth = _tmpl_true(x);
			FREE(ctx->mtype, x);
			if (truth) {
				first = i + 1;
				num = (elem->u.u_if.elsie != -1) ?
				    elem->u.u_if.elsie - 1 :
				    elem->u.u_if.endif - 1;
			} else if (elem->u.u_if.elsie != -1) {
				first = i + elem->u.u_if.elsie;
				num = elem->u.u_if.endif - elem->u.u_if.elsie;
			}
			if (first != -1) {
				rtn = _tmpl_execute_elems(ctx,
				    elems, first, num);
				if (rtn == RTN_BREAK
				    || rtn == RTN_RETURN
				    || rtn == RTN_CONTINUE)
					goto done;
			}
			i += elem->u.u_if.endif;
			break;
		    }

		case TY_DEFINE:
		    {
			char *errmsg = NULL;
			char *name;

			if (!(name = evaluate_arg(ctx,
			    &errmsg, &elem->call.args[0]))) {
				pr_err(ctx, errno, errmsg);
				FREE(ctx->mtype, errmsg);
				i += elem->u.u_define.enddef;
				break;
			}
#ifdef TMPL_DEBUG
			TDBG("%s%6sDefining function \"%s\" as %d elems"
			     " starting at %d\n", indent _ "" _ name _
			     elem->u.u_define.enddef - 1 _ i + 1);
#endif
			if (_tmpl_set_func(ctx, name, elems + i + 1,
			    elem->u.u_define.enddef - 1) == -1) {
				pr_err(ctx, errno, NULL);
				FREE(ctx->mtype, name);
				i += elem->u.u_define.enddef;
				break;
			}
			FREE(ctx->mtype, name);
			i += elem->u.u_define.enddef;
			break;
		    }

		case TY_ENDLOOP:
		case TY_ENDWHILE:
		case TY_ELSE:
		case TY_ENDIF:
		case TY_ENDDEF:
			break;

		case TY_BREAK:
			rtn = RTN_BREAK;
			goto done;

		case TY_CONTINUE:
			rtn = RTN_CONTINUE;
			goto done;

		case TY_RETURN:
			rtn = RTN_RETURN;
			goto done;

		default:
			assert(0);
		}
	}

	/* If we finished all the elements, that's a normal return */
	rtn = RTN_NORMAL;

done:
	/* Debug */
#if TMPL_DEBUG
	TDBG("%sDone, return is %s\n", indent _ tmpl_rtnstr(rtn));
#endif

	/* Decrease nesting */
	ctx->depth--;

	/* Done */
	return (rtn);
}