Example #1
0
static
void
debug_getthreadinfo(struct gdbcontext *ctx, const char *threadid)
{
	unsigned cpunum;
	char buf[128], xbuf[256];
	size_t i;

	cpunum = getthreadid(threadid);
	if (cpunum >= cpu_numcpus()) {
		debug_send(ctx, "E00");
		return;
	}

	/*
	 * Send back string of whatever info we want. Since gdb
	 * already fetches and prints the frame info, and fetches this
	 * but doesn't seem to print it, I dunno what to send.
	 */

	snprintf(buf, sizeof(buf), "CPU %u", cpunum);

	/* Code as hex for transmission */
	xbuf[0] = 0;
	for (i=0; buf[i]; i++) {
		printbyte(xbuf, sizeof(xbuf), (unsigned char)buf[i]);
	}
	debug_send(ctx, xbuf);
}
Example #2
0
	bool openprocess(DWORD pid, DWORD process_access, DWORD thread_access, PROCESS_INFORMATION& pi) {
		closeprocess(pi);

		static bool ok = setdebugprivilege();
		if (!ok) {
			return false;
		}
		pi.dwProcessId = pid;
		pi.hProcess = OpenProcess(process_access, FALSE, pi.dwProcessId);
		if (!pi.hProcess) {
			closeprocess(pi);
			return false;
		}
		pi.dwThreadId = getthreadid(pi.dwProcessId);
		if (!pi.dwThreadId) {
			closeprocess(pi);
			return false;
		}
		pi.hThread = OpenThread(thread_access, FALSE, pi.dwThreadId);
		if (!pi.hThread) {
			closeprocess(pi);
			return false;
		}
		return true;
	}
Example #3
0
static int xfread(char *buf,int siz,int nel,FILE *fp){
	int rel;

	fPollIn(fp,0);
	errno = 0;
	rel = fread(buf,siz,nel,fp);
	if( rel == 0 ){
		while( !feof(fp) ){
			fPollIn(fp,0);
			rel = fread(buf,siz,nel,fp);
fprintf(stderr,"----[%d] dgzlib:fread(%d)=%d RETRY\n",
getpid(),fileno(fp),rel);
			if( 0 < rel ){
				break;
			}
		}
	}

	if( rel <= 0 ){
		syslog_ERROR("[%X] xfread rcc=%d/%d +%d errno=%d\n",
			getthreadid(),rel,nel,inlen,errno);
	}

	if( 0 < rel ){
		inlen += rel;
		if( errno == EAGAIN ){
//fprintf(stderr,">>>>>>> dgzlib:fread(%d)=%d, errno=%d\n",fileno(fp),rel,errno);
			clearerr(fp);
			errno = 0;
		}
	}
	return rel;
}
Example #4
0
int ismainthread(){
	int tid;
	tid = getthreadid();
	if( main_thread == 0 || main_thread == tid ){
		return tid;
	}
	return 0;
}
Example #5
0
int thread_kill(int tid,int sig){
	if( ThreadKill ){
		if( tid == MAINTHREADID ){
			tid = main_thread;
			syslog_ERROR("Killing main-thread %X <- %X\n",
				tid,getthreadid());
		}
		return (*ThreadKill)(tid,sig);
	}
	return -1;
}
Example #6
0
vfuncp Vsignal_FL(FL_PAR,int sig,vfuncp func){
	ThreadSig *ts;
	vfuncp ofunc;
	int tix;

	if( isWindowsCE() ){
		return 0;
	}
	if( sig < 0 || 32 <= sig ){
		return signal(sig,func);
	}
	if( lMULTIST() ){
		tix = 1+getthreadix();
		setupCSC("Vsignal",sigCSC,sizeof(sigCSC));
		enterCSC(sigCSC);
		ts = &sigs[0][sig];
		if( ts->ts_stat == 0 ){
			ts->ts_stat = 1;
			ts->ts_tid = getthreadid();
			ts->ts_func = signal(sig,sigANY);
			ts->ts_F = FL_F;
			ts->ts_L = FL_L;
		}
		ts = &sigs[tix][sig];
		ofunc = ts->ts_func;
		ts->ts_stat = 1;
		ts->ts_tid = getthreadid();
		ts->ts_func = func;
		ts->ts_F = FL_F;
		ts->ts_L = FL_L;
		leaveCSC(sigCSC);
		if( lTHREADSIG() ){
			fprintf(stderr,"-- %X %d/%d Vsignal(%d,%X) <= %s:%d\n",
				TID,actthreads(),numthreads(),
				sig,xp2i(func),FL_BAR);
		}
		return ofunc;
	}
	ofunc = signal(sig,func);
	return ofunc;
}
Example #7
0
static int getix(int tid){
	int ix;
	if( tid == 0 ){
		tid = getthreadid();
	}
	for( ix = 0; ix < elnumof(threadsSerno); ix++ ){
		if( threads[ix].t_id == tid ){
			return ix;
		}
	}
	return -1;
}
Example #8
0
static int toFlash(XFlash *Xf,PCStr(fmt),...){
	VARGS(16,fmt);

	fprintf(stderr,"####[%4X] XFlash ",PRTID(getthreadid()));
	fprintf(stderr,fmt,VA16);
	fprintf(stderr,"\n");
	if( Xf->xf_xfsockfp != NULL ){
		fprintf(Xf->xf_xfsockfp,fmt,VA16);
		fprintf(Xf->xf_xfsockfp,"\r\n");
		fflush(Xf->xf_xfsockfp);
	}
	return 0;
}
Example #9
0
void servlog(PCStr(fmt),...){
	FILE *lfp;
	VARGS(8,fmt);

	lfp = fopen("c:/tmp/svlog","a");
	if( lfp == NULL ){
		return;
	}
	fprintf(stderr,"[%d] ",getpid());
	fprintf(stderr,fmt,VA8);
	fprintf(lfp,"[%d][%d] ",getpid(),getthreadid());
	fprintf(lfp,fmt,VA8);
	fflush(lfp);
	fclose(lfp);
}
Example #10
0
int destroythreads(){
	int ix;
	int tid;
	int fin = 0;
	int mytid = getthreadid();

	for( ix = 0; ix < elnumof(threads); ix++ ){
		if( tid = threads[ix].t_id ){
			if( tid != mytid ){
				if( thread_destroy(tid) == 0 ){
					fin++;
				}
			}
		}
	}
	return fin;
}
Example #11
0
static
void
debug_checkthread(struct gdbcontext *ctx, const char *threadid)
{
	unsigned cpunum;

	cpunum = getthreadid(threadid);
	if (cpunum >= cpu_numcpus()) {
		debug_send(ctx, "E00");
		return;
	}

	if (!cpu_enabled(cpunum)) {
		debug_send(ctx, "E01");
		return;
	}

	debug_send(ctx, "OK");
}
Example #12
0
static int getthreadixX(int atid){
	int tid,ix;
	int nix = -1;
	int mytid = getthreadid();

	if( atid )
		tid = atid;
	else	tid = mytid;
	/*
	else
	tid = getthreadid();
	*/
	for( ix = 0; ix < elnumof(threads); ix++ ){
		if( threads[ix].t_id == 0 ){
			if( nix < 0 ){
				nix = ix;
			}
		}
		if( tideq(threads[ix].t_id,tid) ){
			return ix;
		}
	}
	if( tid != mytid ){
		porting_dbg("ERROR: getthreadix(%X) non-existing %X %X",
			atid,tid,mytid);
		/* it might exit already (or not yet active) */
		return 0;
	}
	if( 0 <= nix ){
		ix = nix;
		thtabAdd++;
		threadsSerno[ix].t_serno = thtabAdd;
		threadsSerno[ix].t_reqno = 0;
		threads[ix].t_id = tid;
		threads[ix].t_tgid = 0;
		threads[ix].t_F = "new";
		threads[ix].t_L = 0;
		return ix;
	}
	porting_dbg("ERROR: getthreadix() no more threads (%d)",ix);
	return 0;
}
Example #13
0
void execCloseOnFork(PCStr(wh)) {
    int fd,rcode;
    int nulfd;

    for( fd = 0; fd < elnumof(cof_fds); fd++ ) {
        if( cof_fds[fd] != 0 ) {
            if( 0 <= (nulfd = openNull(0)) ) {
                rcode = close(fd);
                dup2(nulfd,fd);
                close(nulfd);
            } else
                rcode = close(fd);

            if( LOG_VERBOSE || lTHREAD() )
                fprintf(stderr,"[%d.%X]execCloseOnFork(%s,%d)=%d\n",
                        getpid(),getthreadid(),wh,fd,rcode);
            syslog_ERROR("{t} execCloseOnFork(%s,%d)=%d\n",wh,fd,rcode);
            cof_fds[fd] = 0;
        }
    }
}
Example #14
0
static FILE *setStopService(PCStr(addr))
{
	/*
	daemonlog("F","####! EMERGENCY STOP !####\n");
	*/
	if( newthreads() || numthreads() || pnumthreads() ){
		extern const char *SSLstage;
		int getXf_list(PVStr(Xf));
		IStr(Xf,128);

		setgotsigTERM(999);
		getXf_list(AVStr(Xf));
		putfLog("####! thread-EMERGENCY-STOP !#### %X in (%s)(%s)(%s)",
			ismainthread(),Xf,SSLstage?SSLstage:"",PRTHstage);
		dumpThreads("thread-EMERGENCY-STOP");
	}
	daemonlog("F","####! EMERGENCY STOP !#### [%d.%X]%X %d/%d\n",
		getpid(),getthreadid(),ismainthread(),
		actthreads(),numthreads());

	return stopServ("setStopService","a",addr);
}
Example #15
0
int dumpThreads(PCStr(wh)){
	int nt = 0;
	int ix;
	int me;
	int tid;
	Thread *tp;

	me = getthreadid();
	for( ix = 0; ix < elnumof(threads); ix++ ){
		tp = &threads[ix];
		if( tid = tp->t_id ){
			putfLog("--TH[%d] %s %04X %04Xg (%s) %s:%d %s %s",
				ix,wh,
				PRTID(tp->t_id),PRTID(tp->t_tgid),
				tp->t_what?tp->t_what:"",
				tp->t_F?tp->t_F:"",tp->t_L,
				tp->t_stat?tp->t_stat:"",
				tid==me?"*":""
			);
			nt++;
		}
	}
	return nt;
}
Example #16
0
/* pkt is null-terminated */
void 
debug_exec(struct gdbcontext *ctx, const char *pkt) 
{
	char *cs;  /* start of the checksum */
	int i;
	int check = 0, scheck;

#ifdef SHOW_PACKETS
	msg("Got packet %s", pkt);
#endif

	if (pkt[0] != '$') {
		return;
	}

	cs = strchr(pkt, '#');
	if (cs == NULL) {
		return;
	}
	*cs = 0;
	cs++;

	for (i=1; pkt[i]; i++) {
		check += pkt[i];
	}

	scheck = strtoul(cs, NULL, 16);
	if (scheck != check % 256) {
		write(ctx->myfd, "-", 1);
		return;
	} else {
		write(ctx->myfd, "+", 1);
	}

	switch (pkt[1]) {
	    case '!':
		/*
		 * Enable extended mode -- extended mode is apparently
		 * where gdb can ask to rerun the program. We can't do
		 * that... although it could probably be arranged.
		 *
		 * Reply with "OK" if extended mode is enabled.
		 */
		debug_notsupp(ctx);
		break;
	    case '?':
		/* Report why the target stopped. */
		debug_send_stopinfo(ctx);
		break;
	    case 'A':
		/*
		 * Set argv[]. We can't do this, although it might make
		 * sense if we grow support for reloading the kernel.
		 */
		debug_notsupp(ctx);
		break;
	    case 'b':
		if (pkt[2] == 0) {
			/* Set serial bit rate; deprecated. */
			debug_notsupp(ctx);
			break;
		}
		else if (pkt[2] == 'c') {
			/* Backward continue - resume executing, backwards */
		}
		else if (pkt[2] == 's') {
			/* Backward single step - execute one insn backwards */
		}
		else {
			/* ? */
		}
		debug_notsupp(ctx);
		break;
	    case 'B':
		/* Set or clear breakpoint; old, deprecated. */
		debug_notsupp(ctx);
		break;
	    case 'c':
		/*
		 * Continue. If an address follows the 'c', continue
		 * from that address. debug_restart() does that.
		 */
		debug_restart(ctx, pkt + 2);
		unset_breakcond();
		break;
	    case 'C':
		/*
		 * Continue with signal. A signal number in hex
		 * follows the C; that may be followed with a
		 * semicolon and an address to continue at. We don't
		 * have signals per se; in theory we could fake up
		 * some mapping of signals to hardware traps, but that
		 * would be difficult to arrange and not serve much
		 * purpose.
		 */
		debug_notsupp(ctx);
		break;
	    case 'd':
		/* Toggle debug flag (whatever that means); deprecated. */
		debug_notsupp(ctx);
		break;
	    case 'D':
		/*
		 * Detach. With a process-id, detach only one process,
		 * if the multiprocess extension is in use.
		 */
		debug_send(ctx, "OK");
		unset_breakcond();
		break;
	    case 'F':
		/*
		 * File I/O extension reply; for now at least we have
		 * no use for this.
		 */
		debug_notsupp(ctx);
		break;
	    case 'g':
		/* Read general-purpose registers */
		debug_register_print(ctx);
		break;
	    case 'G':
		/*
		 * Write general-purpose registers. The G is followed
		 * by a register dump in the same format as the 'g'
		 * reply.
		 */
		// XXX gcc docs say this is required
		debug_notsupp(ctx);
		break;
	    case 'H':
		/*
		 * Hc followed by a thread ID sets the thread that
		 * step and continue operations should affect; Hg
		 * followed by a thread ID sets the thread that
		 * other operations should affect.
		 */
		if (pkt[2] == 'c') {
			debug_notsupp(ctx);
		}
		else if (pkt[2] == 'g') {
			unsigned cpunum;

			cpunum = getthreadid(pkt+3);
			if (cpunum >= cpu_numcpus()) {
				debug_send(ctx, "E00");
				break;
			}
			debug_cpu = cpunum;
			debug_send(ctx, "OK");
		}
		else {
			debug_send(ctx, "OK");
		}
		break;
	    case 'i':
		/* Step by cycle count */
		debug_notsupp(ctx);
		break;
	    case 'I':
		/* Step by cycle count with signal (apparently) */
		debug_notsupp(ctx);
		break;
	    case 'k':
		/* Kill the target */
		// don't do this - debugger hangs up and we get SIGPIPE
		//debug_send(ctx, "OK");
		msg("Debugger requested kill");
		reqdie();
		// To continue running instead of dying, do this instead
		//unset_breakcond();
		break;
	    case 'm':
		/* Read target memory */
		debug_read_mem(ctx, pkt + 2);
		break;
	    case 'M':
		/* Write target memory */
		debug_write_mem(ctx, pkt + 2);
		break;
	    case 'p':
		/* read one register */
		debug_notsupp(ctx);
		break;
	    case 'P':
		/* write one register */
		debug_notsupp(ctx);
		break;
	    case 'q':
		/* General query */
		if (strcmp(pkt + 2, "C") == 0) {
			/* Return current thread id */
			debug_sendf(ctx,"QC%x", mkthreadid(debug_cpu));
		}
		else if (!strcmp(pkt+2, "fThreadInfo")) {
			char buf[128];
			unsigned i;

			strcpy(buf, "m");
			for (i=0; i<cpu_numcpus(); i++) {
				if (!cpu_enabled(i)) {
					continue;
				}
				if (i > 0) {
					strcat(buf, ",");
				}
				printbyte(buf, sizeof(buf), mkthreadid(i));
			}
			debug_send(ctx, buf);
		}
		else if (!strcmp(pkt+2, "sThreadInfo")) {
			debug_send(ctx, "l");
		}
		else if (strcmp(pkt+2, "Offsets") == 0) {
			/* Return info about load-time relocations */ 
			debug_notsupp(ctx);
		}
		else if (strcmp(pkt+2, "Supported") == 0) {
			/* Features handshake */
			debug_notsupp(ctx);
		}
		else if (!strncmp(pkt+2, "ThreadExtraInfo,", 16)) {
			debug_getthreadinfo(ctx, pkt+2+16);
		}
		else {
			debug_notsupp(ctx);
		}
		break;
	    case 'Q':
		/* General set mode (I think) */
		debug_notsupp(ctx);
		break;
	    case 'r':
		/* Reset target - deprecated */
		debug_notsupp(ctx);
		break;
	    case 'R':
		/*
		 * Restart target (only with extended mode enabled).
		 * Do not reply.
		 */
		break;
	    case 's':
		/* Single step */
		debug_restart(ctx, pkt + 2);
		onecycle();
		debug_send_stopinfo(ctx);
		break;
	    case 'S':
		/* Single step with signal */
		debug_notsupp(ctx);
		break;
	    case 't':
		/* search memory for a pattern (underdocumented) */
		debug_notsupp(ctx);
		break;
	    case 'T':
		/* check if a thread is alive (OK - yes; E.. - no) */
		debug_checkthread(ctx, pkt + 2);
		break;
	    case 'v':
		/* various longer commands */
		debug_notsupp(ctx);
		break;
	    case 'X':
		/* Write target memory with a more efficient encoding */
		debug_notsupp(ctx);
		break;
	    case 'z':
	    case 'Z':
		/* insert (Z) or remove (z) one of the following: */
		switch (pkt[2]) {
		    case '0':
			/* set or clear memory breakpoint */
			debug_notsupp(ctx);
			break;
		    case '1':
			/* set or clear hardware breakpoint */
			debug_notsupp(ctx);
			break;
		    case '2':
			/* set or clear write watchpoint */
			debug_notsupp(ctx);
			break;
		    case '3':
			/* set or clear read watchpoint */
			debug_notsupp(ctx);
			break;
		    case '4':
			/* set or clear access watchpoint */
			debug_notsupp(ctx);
			break;
		    default:
			/* ? */
			debug_notsupp(ctx);
			break;
		}
		break;
	    default:
		debug_notsupp(ctx);
		break;
	}
}
Example #17
0
int thread_done(void *xcode){
	int tid;
	tid = getthreadid();
	return thread_doneX(tid,xcode);
}
Example #18
0
int thread_fork(int size,int gtid,PCStr(what),IFUNCP func,...)
{
	int tid;
	int ix;
	int smask,nmask;
	VARGS(8,func);

	if( main_thread == 0 ){
		main_thread = getthreadid();
		main_thread_pid = getpid();
		if( THREAD_WAIT_TIMEOUT ){
			IGNRETZ pipe(ThreadsDone);
			ThreadsWaitTO = 1;
		}
	}
	if( ThreadFork )
	{
		/*
		MyPID = 0;
		*/
		NewThreads++;
		setupCSC("thread_fork",thforkCSC,sizeof(thforkCSC));
		enterCSC(thforkCSC);
		Nthreads++;
		nmask = sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGPIPE);
		smask = sigblock(nmask);
		tid = (*ThreadFork)(size,what,func,VA8);
		if( tid != 0 ){
			ActiveThreads++;
			if( ActiveThreadsMax < ActiveThreads ){
				ActiveThreadsMax = ActiveThreads;
			}
			SpawnedThreads++;
			if( lTHFORKSYNC() ){
				/* should wait the thread to be Started to make
				 * the parallel behavior consistent, but it might
				 * affect signal handling ?
				 */
				void msleep(int ms);
				msleep(0);
			}
			/*
			9.8.5 the thread might exit already, don't add ghost
			if( 0 <= (ix = getthreadixY(tid)) ){
				threads[ix].t_what = what;
			}
			*/
			putpplog("actthreads()++=%d [%X]\n",ActiveThreads,tid);
		}
		sigsetmask(smask);
		leaveCSC(thforkCSC);
		NewThreads--;
		if( lTHREADLOG() ){
			const void *toThd(int tid,int del,int *ser);
			FileSize thd;
			thd = p2llu(toThd(tid,0,0));
			syslog_ERROR("thread_fork(%s %X %X)A%d = %X/%llX\n",
				what,size,gtid,actTid(),tid,thd);
		}
		return tid;
		/*
		return (*ThreadFork)(size,func,VA8);
		*/
	}

	porting_dbg("NO thread_fork() available.");
	exit(-1);
	return -1;
}
Example #19
0
static boolean threadcallscriptverb (bigstring bsscriptname, tyvaluerecord vparams, hdlhashtable hcontext, tyvaluerecord *v) {

	/*
	8.0.4 dmb: handle running code values
	
	9.1b3 AR: copy bsscriptname to processrecord so the thread can be more easily
	identified in the system.compiler.threads table
	*/
	
	hdlprocessrecord hp;
	hdlprocessthread hthread;

	bigstring bsverb;
	boolean fl = false;
	boolean flchained = false;
	tyvaluerecord val;
	hdltreenode hfunctioncall;
	hdltreenode hparamlist;
	hdltreenode hcode;
	hdlhashtable htable;
	tyvaluerecord vhandler;
	hdlhashnode handlernode;
	
	/*build code tree, see langrunscript*/

	pushhashtable (roottable);
	
	fl = langexpandtodotparams (bsscriptname, &htable, bsverb);

	if (fl && htable == nil)
		langsearchpathlookup (bsverb, &htable);

	pophashtable();
	
	if (!fl)
		goto exit;
	
	if (!hashtablelookupnode (htable, bsverb, &handlernode)) {
		
		langparamerror (unknownfunctionerror, bsverb);
		
		goto exit;
		}
	
	vhandler = (**handlernode).val;
	
	/*build a code tree and call the handler, with our error hook in place*/
	
	hcode = nil;
	
	if (vhandler.valuetype == codevaluetype) {

		hcode = vhandler.data.codevalue;
	}
	else if ((**htable).valueroutine == nil) { /*not a kernel table*/
		
		if (!langexternalvaltocode (vhandler, &hcode)) {

			langparamerror (notfunctionerror, bsverb);

			goto exit;
			}
		
		if (hcode == nil) { /*needs compilation*/
			
			if (!langcompilescript (handlernode, &hcode))
				goto exit;
			}
		}
	
	if (!setaddressvalue (htable, bsverb, &val))
		goto exit;
	
	if (!pushfunctionreference (val, &hfunctioncall))
		goto exit;
	
	if (hcontext != nil) {
		
		flchained = (**hcontext).flchained;
		
		if (flchained)
			pushhashtable (hcontext);
		else
			chainhashtable (hcontext); /*establishes outer local context*/
		}

	fl = langbuildparamlist (&vparams, &hparamlist);
	
	if (hcontext != nil) {
		
		if (flchained)
			pophashtable ();
		else
			unchainhashtable ();
		}
	
	if (!fl) {
		
		langdisposetree (hfunctioncall);
		
		goto exit;
		}
	
	if (!pushfunctioncall (hfunctioncall, hparamlist, &hcode)) /*consumes input parameters*/
		goto exit;

	if (!pushbinaryoperation (moduleop, hcode, nil, &hcode)) /*needs this level???*/
		goto exit;

	/*launch separate process, see processruntext*/
	
	newlyaddedprocess = nil; //process manager global

	if (!addnewprocess (hcode, true, nil, (long) 0)) {
		
		langdisposetree (hcode);
		
		goto exit;
		}
	
	/*return thread id*/

	hp = newlyaddedprocess; //process.c global; will be nil if a process wasn't just added
			
	if ((hp == nil) || !scheduleprocess (hp, &hthread))
		return (setlongvalue (0, v));
			
	(**hp).processstartedroutine = &threadverbprocessstarted; //don't dim the menu bar

	copystring (bsscriptname, (**hp).bsname);	/* 9.1b3 AR */

	if (hcontext != nil) {

		Handle hpacked;
		boolean fldummy;

		/*make a copy of the context table*/

		if (!tablepacktable (hcontext, true, &hpacked, &fldummy))
			goto exit;

		if (!tableunpacktable (hpacked, true, &hcontext))
			goto exit;		

		/*set the child thread's context to the copy of the context table*/

		(**hp).hcontext = hcontext;

		/*make sure the copy of the context table will be disposed*/

		(**hp).processkilledroutine = &threaddisposecontext;
		}

	return (setlongvalue (getthreadid (hthread), v));

exit:

	return (false);
	}/*threadcallscriptverb*/
Example #20
0
int clearthreadsix(){
	int tid,ix;
	tid = getthreadid();
	return clearthreadsixX(tid);
}
Example #21
0
static boolean threadfunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
	
	/*
	4.1b3 dmb: new verbs
	
	4.1b5 dmb: added thread.sleep
	
	4.1b6 dmb: make thread.sleepFor take seconds, not ticks
	
	5.0d13 dmb: added v == nil check
	*/
	
	register tyvaluerecord *v = vreturned;
	typrocessid processid;
	unsigned long ticks;
	
	if (v == nil) { /*need Frontier process?*/
		
		switch (token) {
			
			case evaluatefunc:
			case callscriptfunc:
			case sleepfunc:
			case sleepforfunc:
			case sleepticksfunc:
			case issleepingfunc:
			case wakefunc:
			case killfunc:
			/*
			case begincriticalfunc:
			case endcriticalfunc:
			*/
			case statsfunc:
				return (true);
			
			case existsfunc:
			case getcurrentfunc:
			case getcountfunc:
			case getnththreadfunc:
			case gettimeslicefunc:
			case getdefaulttimeslicefunc:
			case settimeslicefunc:
			case setdefaulttimeslicefunc:
			default:
				return (false);
			}
		}
	
	setbooleanvalue (false, v); // assume the worst
	
	processid = getcurrentprocessid ();
	
	if (!iscurrentapplication (processid)) {
		
		getstringlist (langerrorlist, cantbackgroundclipboard, bserror);	// ***
		
		return (false);
		}
	
	switch (token) {
		
		case existsfunc: {
			long id;
			
			flnextparamislast = true;
			
			if (!getlongvalue (hparam1, 1, &id))
				return (false);
			
			return (setbooleanvalue (getprocessthread (id) != nil, v));
			}
		
		case evaluatefunc: {
			Handle htext;
			hdlprocessrecord hp;
			hdlprocessthread hthread;
			
			flnextparamislast = true;
			
			if (!getexempttextvalue (hparam1, 1, &htext))
				return (false);
			
			newlyaddedprocess = nil; //process manager global
			
			if (!processruntext (htext))
				return (false);
			
			hp = newlyaddedprocess; //process.c global; will be nil if a process wasn't just added
			
			if ((hp == nil) || !scheduleprocess (hp, &hthread))
				return (setlongvalue (0, v));
			
			(**hp).processstartedroutine = &threadverbprocessstarted;

			return (setlongvalue (getthreadid (hthread), v));
			}
		
		case callscriptfunc: {

			bigstring bsscriptname;
			tyvaluerecord vparams;
			hdlhashtable hcontext = nil;
			boolean fl;
	
			if (!getstringvalue (hparam1, 1, bsscriptname))
				return (false);
	
			if (!getparamvalue (hparam1, 2, &vparams))
				return (false);
	
			if (vparams.valuetype != recordvaluetype)
				if (!coercetolist (&vparams, listvaluetype))
					return (false);
	
			if (langgetparamcount (hparam1) > 2) {
		
				flnextparamislast = true;

				if (!gettablevalue (hparam1, 3, &hcontext))
					return (false);
				}
				
			(**(getcurrentthreadglobals ())).debugthreadingcookie = token;

			fl = threadcallscriptverb (bsscriptname, vparams, hcontext, v);
			
			(**(getcurrentthreadglobals ())).debugthreadingcookie = 0;

			return (fl);
			}

		case getcurrentfunc:
			if (!langcheckparamcount (hparam1, 0))
				return (false);
			
			return (setlongvalue (getthreadid (getcurrentthread ()), v));
		
		case getcountfunc:
			if (!langcheckparamcount (hparam1, 0))
				return (false);
			
			return (setlongvalue (processthreadcount (), v));
		
		case getnththreadfunc: {
			short n;
			
			flnextparamislast = true;
			
			if (!getintvalue (hparam1, 1, &n))
				return (false);
			
			return (setlongvalue (getthreadid (nthprocessthread (n)), v));
			}
		
		case sleepfunc: {
			hdlprocessthread hthread;
			
			flnextparamislast = true;
			
			if (!getthreadvalue (hparam1, 1, &hthread))
				return (false);
			
			return (setbooleanvalue (processsleep (hthread, -1), v));
			}
		
		case sleepforfunc: {
			long n;
			boolean fl;
			
			flnextparamislast = true;
			
			if (!getlongvalue (hparam1, 1, &n))
				return (false);
			
			(**(getcurrentthreadglobals ())).debugthreadingcookie = token;

			fl = processsleep (getcurrentthread (), n * 60);
			
			(**(getcurrentthreadglobals ())).debugthreadingcookie = 0;

			return (setbooleanvalue (fl, v));
			}
		
		case sleepticksfunc: {
			long n;
			boolean fl;
			
			flnextparamislast = true;
			
			if (!getlongvalue (hparam1, 1, &n))
				return (false);
			
			(**(getcurrentthreadglobals ())).debugthreadingcookie = token;

			fl = processsleep (getcurrentthread (), n);
			
			(**(getcurrentthreadglobals ())).debugthreadingcookie = 0;

			return (setbooleanvalue (fl, v));
			}

		case issleepingfunc: {
			hdlprocessthread hthread;
			
			flnextparamislast = true;
			
			if (!getthreadvalue (hparam1, 1, &hthread))
				return (false);
			
			return (setbooleanvalue (processissleeping (hthread), v));
			}
		
		case wakefunc: {
			hdlprocessthread hthread;
			
			flnextparamislast = true;
			
			if (!getthreadvalue (hparam1, 1, &hthread))
				return (false);
			
			return (setbooleanvalue (wakeprocessthread (hthread), v));
			}
		
		case killfunc: {
			hdlprocessthread hthread;
			
			flnextparamislast = true;
			
			if (!getthreadvalue (hparam1, 1, &hthread))
				return (false);
			
			return (setbooleanvalue (killprocessthread (hthread), v));
			}
		
		case gettimeslicefunc:
			if (!langcheckparamcount (hparam1, 0))
				return (false);
			
			getprocesstimeslice (&ticks);

			return (setlongvalue (ticks, v));
		
		case settimeslicefunc:
			flnextparamislast = true;

			if (!getlongvalue (hparam1, 1, (long *) (&ticks)))
				return (false);
			
			return (setbooleanvalue (setprocesstimeslice (ticks), v));
	
		case getdefaulttimeslicefunc:
			if (!langcheckparamcount (hparam1, 0))
				return (false);
			
			getdefaulttimeslice (&ticks);

			return (setlongvalue (ticks, v));
		
		case setdefaulttimeslicefunc:
			flnextparamislast = true;

			if (!getlongvalue (hparam1, 1, (long *) (&ticks)))
				return (false);
			
			return (setbooleanvalue (setdefaulttimeslice (ticks), v));
		/*
		case begincriticalfunc:
			if (!langcheckparamcount (hparam1, 0))
				return (false);
			
			++fldisableyield;
			
			return (setbooleanvalue (true, v));
		
		case endcriticalfunc:
			if (!langcheckparamcount (hparam1, 0))
				return (false);
			
			if (fldisableyield > 0) {
			
				--fldisableyield;
				
				(*v).data.flvalue = true;
				}
			
			return (true);
		*/
		case statsfunc:
			return (threadstatsverb (hparam1, v));

		default:
			return (false);
		}
	} /*threadfunctionvalue*/
Example #22
0
/*
 * I/O timeout in seconds
 */
int IO_TIMEOUT = (10*60);

#include "proc.h"
typedef struct {
	int	t_x;
	int	t_pid;
	double	t_Time;
	int	t_id;
	int	t_fd;
	int	t_timer;
	int	t_sig;
 void (*t_pipe)(int sig);
	int	t_sser;
	int	t_cln;
 sigjmp_buf	t_ioenv;
} ThreadIO;
static int sser[MAX_THREADS]; /* setjmp serial */
static int nsig[MAX_THREADS];
static int threadPID[MAX_THREADS];
static ThreadIO *threadIO[MAX_THREADS];

void clearThreadFilter();
void clearThreadEnv(){
	int ti;

	for( ti = 0; ti < MAX_THREADS; ti++ ){
		if( threadIO[ti] ){
			sv1log("-- clearThreadEnv[%d] %X %d %d %d\n",
				ti,p2i(threadIO[ti]),sser[ti],nsig[ti],threadPID[ti]);
		}
		threadIO[ti] = 0;
		sser[ti] = 0;
		nsig[ti] = 0;
		threadPID[ti] = 0;
	}
	clearThreadFilter();
}
void clearThreadSig(){
	int ti;
	for( ti = 0; ti < MAX_THREADS; ti++ ){
		if( nsig[ti] ){
			sv1log("-- clearThreadSig[%d] %d %d\n",ti,
				nsig[ti],sser[ti]);
		}
		nsig[ti] = 0;
	}
}

int getmtpid();
static int okenv(ThreadIO *tio){
	int off = (char*)tio - (char*)&tio;
	if( tio->t_x < 0 || elnumof(threadIO) <= tio->t_x ){
		porting_dbg("--stale ThreadIO %X %X x=%X",p2i(tio),off,tio->t_x);
		return 0;
	}
	if( tio->t_sser != sser[tio->t_x] ){
		porting_dbg("--stale ThreadIO %X %X ser=%X/%X",p2i(tio),off,
			tio->t_sser,sser[tio->t_x]);
		return 0;
	}
	if( tio->t_pid != getmtpid() ){
		porting_dbg("--stale ThreadIO %X %X pid=%d/%d tid=%X",p2i(tio),off,
			tio->t_pid,getmtpid(),tio->t_id
		);
		return 0;
	}
	return 1;
}

int gotSIGPIPE(){
	return nsig[getthreadix()];
}
int iamServer();
int MAX_SIGPIPE = 100; /* max. SIGPIPE caught in an output action */
static void io_timeout(int sig){
	ThreadIO *myenv;
	ThreadIO *ev1;
	int mx,my_tid,tid,tid1;
	int tn,tx,ti;
	int my_pid;

	Vsignal(SIGPIPE,io_timeout); /*should be before thread_kill()*/
	if( sig == SIGPIPE ){
		/* should not do longjump() to set ferror()...
		 * and maybe the longjump() on SIGPIPE is not necessaly.
		 * 9.8.2 set explicitly by Setferror() as an workaround
		 */
		if( lNOSIGPIPE() ){
			return;
		}
	}

	mx = getthreadix();
	my_tid = getthreadid();
	myenv = threadIO[mx];
	sv1log("IO_TIMEOUT[%d] SIGPIPE got by[%X] longjump %X[%X] %d/%d\n",
		mx,my_tid,p2i(myenv),myenv?myenv->t_id:0,
		actthreads(),numthreads());
	if( numthreads() ){
		if( isatty(fileno(stderr)) )
		fprintf(stderr,"-- %X gotSIGPIPE(%d) [%d]%X[%X] %d/%d\n",
			TID,sig,mx,p2i(myenv),myenv?myenv->t_id:0,
			actthreads(),numthreads());
	}

	if( myenv && myenv->t_id == my_tid && okenv(myenv) ){
		nsig[mx] += 1;
		if( myenv->t_sig != 0 ){
			sv1log("IO_TIMEOUT[%d] SIG*%d (%d %d) in longjump\n",
				mx,nsig[mx],myenv->t_sig,sig);
			if( MAX_SIGPIPE < nsig[mx] )
			if( !lSINGLEP() && !iamServer() ){
				sv1log("####Finish: Too Many SIGPIPE: %d\n",
					nsig[mx]);
				Finish(-1);
			}
			return;
		}
		myenv->t_sig = sig;
		siglongjmpX(myenv->t_ioenv,sig);
		return;
	}

	tid = 0;
	my_pid = getmtpid();
	for( tn = 0; tn < elnumof(threadIO); tn++ ){
		tx = (mx + 1 + tn) % elnumof(threadIO);
		if( threadPID[tx] != my_pid ){
			threadIO[tx] = 0;
			continue;
		}
		if( (ev1 = threadIO[tx]) == 0 /*|| !validenv(tx,ev1) */ ){
			continue;
		}
		if( !okenv(ev1) ){
			threadIO[tx] = 0;
			continue;
		}
		if( (tid1 = ev1->t_id) == 0 )
			continue;
		sv1log("IO_TIMEOUT[%d] candidate %X [%d]\n",
			tx,tid1,ev1->t_fd);
		if( tid == 0 ){
			tid = tid1;
		}
		porting_dbg("candidate handler IO_TIMEOUT[%d] %X [%d]",
			tx,tid,ev1->t_fd);
		nsig[tx] += 1;
		break;
	}
	if( tid == my_tid ){
		sv1log("IO_TIMEOUT: dangling? SIG%d -> %X\n",sig,my_tid);
		porting_dbg("IO_TIMEOUT: dangling? SIG%d -> %X ++++",
			sig,my_tid);
	}else
	if( tid ){
		porting_dbg("IO_TIMEOUT: forwarded SIG%d %X -> %X",
			sig,my_tid,tid);
		sv1log("IO_TIMEOUT: forwarded SIG%d %X -> %X\n",
			sig,my_tid,tid);
		thread_kill(tid,sig);
	}else{
		sv1log("IO_TIMEOUT: dangling SIG%d -> %X\n",sig,my_tid);
		porting_dbg("IO_TIMEOUT: dangling SIG%d -> %X ----",
			sig,my_tid);
	}

}
Example #23
0
static void gotSIG(PCStr(F),int L,ThreadIO *myenv,int timeout){
	sv1log("IO_TIMOEUT[%d]%X %X longreturn SIG%s timeout=%d [%d] %s:%d/%d\n",
		getthreadix(),getthreadid(),myenv->t_id,
		sigsym(myenv->t_sig),timeout,
		myenv->t_fd,F,L,myenv->t_cln);
}
Example #24
0
int gzipFilterX(FILE *in,FILE *out,SyncXF syncf,void *sp,int si){
	gzFile gz;
	int len,rcc;
	CStr(buf,1024*8);
	int size;
	int gsize;
	int wcc;
	int bcc = 0;
	double Start = Time();
	double Prevf = 0;
	int ibz = sizeof(buf);
	int gi;
	int fd = -1;
	int ofd = fileno(out);
	int xfd;
	int zerr = 0;
	/*
	int rready = -1;
	*/

	errno = 0;
	fd = dup(fileno(out));
	if( fd < 0 ){
		syslog_ERROR("--gzipFilter[%d]<-[%d] errno=%d\n",fd,ofd,errno);
		return -1;
	}

	/*
	if( 0 <= GZIPready )
		rready = dup(GZIPready);
	*/
	len = 0;
	/*
	if( gz = GZdopen(dup(fileno(out)),"w") ){
	*/
	if( file_isSOCKET(ofd) || file_ISSOCK(ofd) )
	if( !IsConnected(ofd,NULL) || !IsAlive(ofd) ){

fprintf(stderr,"[%d.%X] gzip DISCONN\n",getpid(),getthreadid());
fprintf(stderr,"[%d.%X] gzip DISCONN fd[%d] con=%d isSOCK=%d,%d,%d\n",
getpid(),getthreadid(),ofd,IsConnected(ofd,NULL),
file_isSOCKET(ofd),file_ISSOCK(ofd),file_issock(ofd));

		sendsync(rready,1);
		close(fd);
		return -1;
	}
	gz = GZdopen(fd,"w");
	if( file_isSOCKET(ofd) || file_ISSOCK(ofd) )
	if( !IsConnected(ofd,NULL) || !IsAlive(ofd) ){

fprintf(stderr,"[%d.%X] gzip DISCONN gx=%d\n",getpid(),getthreadid(),p2i(gz));
fprintf(stderr,"[%d.%X] gzip DISCONN fd[%d] con=%d isSOCK=%d,%d,%d\n",
getpid(),getthreadid(),ofd,IsConnected(ofd,NULL),
file_isSOCKET(ofd),file_ISSOCK(ofd),file_issock(ofd));

		close(fd);
		sendsync(rready,2);
		close(fd);
		return -1;
	}

	if( gz ){
		LOGX_gzip++;
		if( Gzip_NoFlush ){
			GZDBG(stderr,"-- %X gzip flush disabled(%d)\n",
				TID,Gzip_NoFlush);
		}
		Prevf = Time();

		sendsync(rready,0);
		setCloseOnFork("GZIPstart",fd);
		/*
		while( rcc = fread(buf,1,sizeof(buf),in) ){
		*/
		for( gi = 0;; gi++ ){
			if( gotsigTERM("gzip gi=%d",gi) ){
				if( numthreads() && !ismainthread() ){
					thread_exit(0);
				}
				break;
			}
			if( !Gzip_NoFlush )
			if( bcc )
			if( 0 < len && finputReady(in,NULL) == 0 ){
				zerr =
				gzflush(gz,Z_SYNC_FLUSH);
if( zerr ){
porting_dbg("+++EPIPE[%d] gzflush() zerr=%d %d SIG*%d",fd,zerr,len,gotSIGPIPE());
}
				bcc = 0;
			}
			if( lSINGLEP() ) /* could be generic */
			{
				if( 0 < len )
				if( !Gzip_NoFlush
				 || 4 < gi && 5 < Time()-Prevf
				){
				GZDBG(stderr,"-- %X gzip flush %d(%f) %d/%d\n",
				TID,Gzip_NoFlush,Time()-Start,len,gi);
					Prevf = Time();
					zerr = gzflush(gz,Z_SYNC_FLUSH);
					bcc = 0;
					if( zerr ){
				GZDBG(stderr,"-- %X gzip gzflush()%d err=%d\n",
				TID,len,zerr);
						break;
					}
				}
			}
			/*
			rcc = fread(buf,1,sizeof(buf),in);
			*/
			rcc = xread(in,AVStr(buf),QVSSize(buf,ibz));

			if( rcc <= 0 ){
				break;
			}
			wcc =
			gzwrite(gz,buf,rcc);

//fprintf(stderr,"[%d] Gzwrite %d/%d / %d\n",getpid(),wcc,rcc,len);

if( wcc <= 0 ){
porting_dbg("+++EPIPE[%d] gzwrite() %d/%d %d SIG*%d",fd,wcc,rcc,len,gotSIGPIPE());
fprintf(stderr,"[%d] Gzwrite %d/%d / %d\n",getpid(),wcc,rcc,len);
break;
}

			if( wcc != rcc ){
				syslog_ERROR("gzwrite %d/%d\n",wcc,rcc);
			}
			if( 0 < wcc ){
				bcc += wcc;
			}
			if( sizeof(buf) <= len ){
				ibz = sizeof(buf);
			}
			if( !Gzip_NoFlush )
			if( bcc )
			if( sizeof(buf) <= bcc || len < 16*1024 ){
				zerr =
				gzflush(gz,Z_SYNC_FLUSH);
				bcc = 0;
			}
			if( zerr || gotSIGPIPE() ){
porting_dbg("+++EPIPE[%d] gzflush() zerr=%d %d SIG*%d",fd,zerr,len,gotSIGPIPE());
				break;
			}
			len += rcc;
		}
		if( len == 0 ){
			const char *em;
			int en;
			int ef;
			em = gzerror(gz,&en);
			ef = gzeof(gz);
			if( en == -1 /* see errno */ && errno == 0 ){
				/* no error */
			}else{
			daemonlog("F","FATAL: gzwrite(%d)=%d/%d eof=%d %d %s\n",
				fd,len,bcc,ef,en,em);
			porting_dbg("FATAL: gzwrite(%d)=%d/%d eof=%d %d %s",
				fd,len,bcc,ef,en,em);
			}
		}
		clearCloseOnFork("GZIPend",fd);
		gzflush(gz,Z_SYNC_FLUSH);
		xfd = dup(fd);
		gsize = GZtell(gz);
		GZclose(gz);
		if( isWindowsCE() || lMULTIST() ){
			/* duplicated close of fd is harmful */
		}else
		if( isWindows() ) close(fd); /* to clear osf-handle mapping */
		Lseek(xfd,0,2);
		size = Lseek(xfd,0,1);
		Lseek(xfd,0,0);
		close(xfd);
		syslog_DEBUG("(%f)gzipFilter %d -> %d / %d\n",Time()-Start,
			len,gsize,size);
		return len;
	}
	sendsync(rready,3);
	close(fd);
	return 0;
}
Example #25
0
static int getConnSocket(int sock,SAP addr,int leng,int *rcsock,int *pending){
	int si;
	int csi = -1;
	SockPool *sp;
	int got_csock = -1;
	double Now = Time();
	double Age = 0;
	static int getOk;
	static int getNg;
	int rcode = -1;

	setupCSC("getConnSocket",sockCSC,sizeof(sockCSC));
	enterCSC(sockCSC);
	*pending = 0;
	for( si = 0; si < elnumof(sockPool); si++ ){
		sp = &sockPool[si];
		if( sp->sp_Time == 0 )
			continue;
		if( PCON_TIMEOUT < Now - sp->sp_Time ){
			LOGX_tcpConAbandon2++;
			abandon(sp,1);
			continue;
		}
		if( sp->sp_leng != leng ){
			continue;
		}
		if( bcmp(addr,&sp->sp_addr,leng) != 0
		 && VSA_addrcomp((VSAddr*)addr,&sp->sp_addr) != 0
		){
			continue;
		}
		rcode = sp->sp_rcode;
		if( rcode == RCODE_RECYC ){
			if( /* HTTP && */ inoutReady(sp->sp_sock,1)
			 || !sock_isconnected(sp->sp_sock)
			){
				getNg++;
	/*
	porting_dbg("--getConnSock(%d/%d) age=%.2f [%d] NO-R %d:%d",
	si,sockPoolN,Now-sp->sp_Time,sp->sp_sock,getNg,getOk);
	*/
				LOGX_tcpConAbandon3++;
				abandon(sp,2);
				continue;
			}
			LOGX_tcpConRecycleOk++;
		}else{
			if( inoutReady(sp->sp_sock,2) == 0 ){
				if( PCON_TIMEOUT < Now - sp->sp_Time ){
	porting_dbg("--getConnSock(%d/%d)%s age=%.2f [%d] NO-A",
	si,sockPoolN,sp->sp_what,Now-sp->sp_Time,sp->sp_sock);
					LOGX_tcpConAbandon4++;
					abandon(sp,3);
				}else{
					*pending += 1;
				}
				continue;
			}
			if( !sock_isconnected(sp->sp_sock) ){
	porting_dbg("--getConnSock(%d/%d)%s age=%.2f [%d] NO-B",
	si,sockPoolN,sp->sp_what,Now-sp->sp_Time,sp->sp_sock);
				LOGX_tcpConAbandon4++;
				abandon(sp,3);
				continue;
			}
		}
		getOk++;
	if( rcode != RCODE_RECYC )
	porting_dbg("--getConnSock(%d/%d)%s age=%.2f [%d] OK (%d)",
	si,sockPoolN,sp->sp_what,Now-sp->sp_Time,sp->sp_sock,getOk);
	syslog_ERROR("--getConnSock(%d/%d)%s age=%.2f [%d] OK (%d)\n",
	si,sockPoolN,sp->sp_what,Now-sp->sp_Time,sp->sp_sock,getOk);

		Age = Now - sp->sp_Time;
		sp->sp_Time = 0;
		sockPoolN--;
		csi = si;
		got_csock = sp->sp_sock;
		break;
	}
	leaveCSC(sockCSC);

	if( got_csock < 0 ){
		return -1;
	}

if( rcode != RCODE_RECYC )
porting_dbg("--getConnSocket(%d)[%d]>>>%d[%d]",
sockPoolN,sock,csi,got_csock);

	setfdowner(got_csock,getthreadid(),getthreadgid(0));
	*rcsock = got_csock;
	syslog_ERROR("--getConnSocket([%d]%d)<-[%d]%d %.2f (%d)\n",
		sock,SocketOf(sock),got_csock,SocketOf(got_csock),
		Age,*pending);
	return 0;
}