Beispiel #1
0
/**
   Setting up aperture cordinate grid aper_locs, and amplitude map for
performance evaluation. */
APER_T * setup_aper(const PARMS_T *const parms){
    APER_T *aper = mycalloc(1,APER_T);
    tic;
    if(parms->aper.fnamp){
	info2("Reading aperture amplitude map from %s\n", parms->aper.fnamp);
	aper->ampground=mapread("%s",parms->aper.fnamp);
	if(fabs(aper->ampground->h)>1.e-14){
	    warning("ampground is not on ground, this is not tested\n");
	}else{
	    double amp_d, amp_din;
	    map_d_din(aper->ampground, &amp_d, &amp_din);
	    if(fabs(parms->aper.d - amp_d) > 1 ||
	       fabs(parms->aper.din - amp_din) > 0.5){
		if(!parms->aper.fnampuser){
		    warning2("Amplitude map does not match aperture diameter: amp.d=(%g, %g) aper.d=(%g, %g). Disabled\n", 
			     amp_d, amp_din, parms->aper.d, parms->aper.din);
		    mapfree(aper->ampground);
		    free(((PARMS_T*)parms)->aper.fnamp);
		    ((PARMS_T*)parms)->aper.fnamp=0;
		}else{
		    error("Use supplied amplitude map does not match aperture diameter: amp.d=(%g, %g) aper.d=(%g, %g).\n", 
			  amp_d, amp_din, parms->aper.d, parms->aper.din);
		}
	    }
	}
	if(fabs(parms->aper.rotdeg)>1.e-12){
	    warning("Pupil is rotated by %g deg\n",parms->aper.rotdeg);
	    const long nx=aper->ampground->nx;
	    const long ny=aper->ampground->ny;
	    dmat *B=dnew_data(nx, ny, aper->ampground->p);
	    aper->ampground->p=mycalloc(nx*ny,double);
	    dembed((dmat*)aper->ampground,B,parms->aper.rotdeg/180.*M_PI);
	    dfree(B);
	}
Beispiel #2
0
static void signal_handler(int sig, self_code_info_t *info, self_sig_context_t *scp) {
  if (InterruptedContext::the_interrupted_context->forwarded_to_self_thread(sig))
    return;
 
  if (SignalInterface::currentNonTimerSignal || SignalInterface::currentTimerSignal) {
      fatal3("signal_handler:  cannot nest (only one interrupted context).\n"
             "Received sig %d while in sig %d or timer sig %d.\n"
             "MacOSX ApplicationEnhancer causes apps to get signals that should be blocked.",
             sig, SignalInterface::currentNonTimerSignal, SignalInterface::currentTimerSignal);
    }

    SignalInterface::currentNonTimerSignal = sig;

    sigset_t oset;
    if (sigprocmask(0, NULL, &oset) != 0) {
      perror("sigprocmask");
      fatal("sigprocmask failed");
    }
    if (!sigismember(&oset, sig))
    # ifdef ROSETTA
        warning2("signal %d is not member of 0x%x", sig, oset);
    # else
        fatal2("signal %d is not member of 0x%x", sig, (int*)(int*)&oset);
    # endif
      
    InterruptedContext::the_interrupted_context->set(scp);
    SignalInterface::handle_signal( sig, 
                                    info == NULL  ?  NULL  :  (char*)info->si_addr, 
                                    info == NULL  ?  NULL  :         info->si_code );
    InterruptedContext::the_interrupted_context->invalidate();

    SignalInterface::currentNonTimerSignal = 0;
  }
Beispiel #3
0
/* Add a parameter to the current element */
void addpar(M_NOPAR)
{
PARAMETER *paramp, *last = NULL ;
int length ;

parcount++ ;
pcount++ ;
for (paramp = plist ; paramp ; paramp = paramp->next)
    {
    if (w_strcmp(name, paramp->paramname) == 0)
    warning2("Multiple definition of parameter %s for element %s",
             name,
	     thisrule) ;
    last = paramp ;
    }
newpar = (PARAMETER *) m_malloc(sizeof(PARAMETER), "parameter") ;
if (! plist)
    plist = newpar ;
else
    last->next = newpar ;
*nextpar = newpar ;
nextpar = &newpar->nextptr ;
*nextpar = NULL ;
newpar->next = NULL ;
newpar->deftype = NULLDEF ;
newpar->defval = M_NULLVAL ;
newpar->defstring = NULL ;
newpar->kwlist = M_NULLVAL ;
length = w_strlen(name) + 1 ;
pnamelen += length ;
newpar->paramname = (M_WCHAR *) m_malloc(length, "parameter name") ;
w_strcpy(newpar->paramname, name) ;
newpar->ptypep = NULL ;
}
Beispiel #4
0
int32 MonitorSampledBar::used2() {
  int32 u = sum3 + sum4;
  int32 c = capacity();
  // this can exceed capacity slightly due to sampling errors
  if (u > 2*c)
    warning2("MonitorSampledBar: usage(2) is way too high: %ld >> %ld", u, c);
  return u <= c ? u : c;
}
Beispiel #5
0
bool XPlatformWindow::open_xdisplay(const char *n) {
  if (n == NULL) n = "";
  _display = XOpenDisplay(n);
  if (_display == NULL) {
    warning2("cannot open X display '%s' a.k.a. '%s'! window won't work.",
             n, XDisplayName(n));
    return false;
  }
  return true;
}
Beispiel #6
0
/**
  Connect to a host at port.
  hostname may start with / to indicate a local UNIX port
*/
int connect_port(const char *hostname, int port, int block, int nodelay){
    int sock=-1;
    if(hostname[0]=='/'){//connect locally so we can pass fd.
	sock = socket(PF_UNIX, SOCK_STREAM, 0);
	struct sockaddr_un addr={0};
	addr.sun_family=AF_UNIX;
	strncpy(addr.sun_path, hostname, sizeof(addr.sun_path)-1);
	if(connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_un))<0){
	    warning("connect locally failed: %s\n", strerror(errno));
	    close(sock);
	    sock=-1;
	}
	return sock;
	//hostname="localhost";
    }else{
	//if(sock!=-1) return sock;
	struct sockaddr_in servername;
	for(int count=0; count<25; count++){
	    sock = socket (PF_INET, SOCK_STREAM, 0);
	    socket_tcp_keepalive(sock);
	    if(nodelay){
		socket_tcp_nodelay(sock);
	    }
	    if(!block){
		socket_block(sock, 0);
	    }
	    int res;
	    struct addrinfo *result;
	    struct addrinfo hints={0};
	    hints.ai_family=AF_INET;
	    hints.ai_socktype=SOCK_STREAM;
	    char portstr[20];
	    snprintf(portstr, 20, "%d", port);
	    if((res=getaddrinfo(hostname, portstr, &hints, &result))){
		warning("getaddrinfo for %s failed with %d: %s\n", hostname, res, gai_strerror(res));
		return -1;
	    }
	    res=connect(sock, result->ai_addr, sizeof (servername));
	    freeaddrinfo(result);
	    /* Give the socket the target hostname. */
	    if(res<0){
		warning2("connect to %s at %d failed: %s\n", hostname, port, strerror(errno));
		close(sock);
		if(!block){
		    return -1;
		}
		sleep(10);
	    }else{
		return sock;
	    }
	}
    }
    return -1; 
}
Beispiel #7
0
static OSStatus playProc(AudioConverterRef inAudioConverter,
						 UInt32 *ioNumberDataPackets,
                         AudioBufferList *outOutputData,
                         AudioStreamPacketDescription **outDataPacketDescription,
                         void* inClientData)
{
	mpg123_coreaudio_t *ca = (mpg123_coreaudio_t *)inClientData;
	long n;
	
	
	if(ca->last_buffer) {
		ca->play_done = 1;
		return noErr;
	}
	
	for(n = 0; n < outOutputData->mNumberBuffers; n++)
	{
		unsigned int wanted = *ioNumberDataPackets * ca->channels * ca->bps;
		unsigned char *dest;
		unsigned int read;
		if(ca->buffer_size < wanted) {
			debug1("Allocating %d byte sample conversion buffer", wanted);
			ca->buffer = realloc( ca->buffer, wanted);
			ca->buffer_size = wanted;
		}
		dest = ca->buffer;
		
		/* Only play if we have data left */
		if ( sfifo_used( &ca->fifo ) < (int)wanted ) {
			if(!ca->decode_done) {
				warning("Didn't have any audio data in callback (buffer underflow)");
				return -1;
			}
			wanted = sfifo_used( &ca->fifo );
			ca->last_buffer = 1;
		}
		
		/* Read audio from FIFO to SDL's buffer */
		read = sfifo_read( &ca->fifo, dest, wanted );
		
		if (wanted!=read)
			warning2("Error reading from the ring buffer (wanted=%u, read=%u).\n", wanted, read);
		
		outOutputData->mBuffers[n].mDataByteSize = read;
		outOutputData->mBuffers[n].mData = dest;
	}
	
	return noErr; 
}
Beispiel #8
0
/* The audio function callback takes the following parameters:
       stream:  A pointer to the audio buffer to be filled
       len:     The length (in bytes) of the audio buffer
*/
static void audio_callback_sdl(void *udata, Uint8 *stream, int len)
{
	out123_handle *ao = (out123_handle*)udata;
	sfifo_t *fifo = (sfifo_t*)ao->userptr;
	int bytes_read;
	int bytes_avail;

	bytes_avail = sfifo_used(fifo);
	if(bytes_avail < len) len = bytes_avail;

	/* Read audio from FIFO to SDL's buffer */
	bytes_read = sfifo_read( fifo, stream, len );

	if (len!=bytes_read)
	warning2("Error reading from the FIFO (wanted=%u, bytes_read=%u).\n", len, bytes_read);
}
Beispiel #9
0
/**
   Time domain physical simulation.
   
   noisy: 
   - 0: no noise at all; 
   - 1: poisson and read out noise. 
   - 2: only poisson noise.   
*/
dmat *skysim_sim(dmat **mresout, const dmat *mideal, const dmat *mideal_oa, double ngsol, 
		 ASTER_S *aster, const POWFS_S *powfs, 
		 const PARMS_S *parms, int idtratc, int noisy, int phystart){
    int dtratc=0;
    if(!parms->skyc.multirate){
	dtratc=parms->skyc.dtrats->p[idtratc];
    }
    int hasphy;
    if(phystart>-1 && phystart<aster->nstep){
	hasphy=1;
    }else{
	hasphy=0;
    }
    const int nmod=mideal->nx;
    dmat *res=dnew(6,1);/*Results. 1-2: NGS and TT modes., 
			  3-4:On axis NGS and TT modes,
			  4-6: On axis NGS and TT wihtout considering un-orthogonality.*/
    dmat *mreal=NULL;/*modal correction at this step. */
    dmat *merr=dnew(nmod,1);/*modal error */
    dcell *merrm=dcellnew(1,1);dcell *pmerrm=NULL;
    const int nstep=aster->nstep?aster->nstep:parms->maos.nstep;
    dmat *mres=dnew(nmod,nstep);
    dmat* rnefs=parms->skyc.rnefs;
    dcell *zgradc=dcellnew3(aster->nwfs, 1, aster->ngs, 0);
    dcell *gradout=dcellnew3(aster->nwfs, 1, aster->ngs, 0);
    dmat *gradsave=0;
    if(parms->skyc.dbg){
	gradsave=dnew(aster->tsa*2,nstep);
    }
   
    
    SERVO_T *st2t=0;
    kalman_t *kalman=0;
    dcell *mpsol=0;
    dmat *pgm=0;
    dmat *dtrats=0;
    int multirate=parms->skyc.multirate;
    if(multirate){
	kalman=aster->kalman[0];
	dtrats=aster->dtrats;
    }else{
	if(parms->skyc.servo>0){
	    const double dtngs=parms->maos.dt*dtratc;
	    st2t=servo_new(merrm, NULL, 0, dtngs, aster->gain->p[idtratc]);
	    pgm=aster->pgm->p[idtratc];
	}else{
	    kalman=aster->kalman[idtratc];
	}
    }
    if(kalman){
	kalman_init(kalman);
	mpsol=dcellnew(aster->nwfs, 1); //for psol grad.
    }
    const long nwvl=parms->maos.nwvl;
    dcell **psf=0, **mtche=0, **ints=0;
    ccell *wvf=0,*wvfc=0, *otf=0;
    if(hasphy){
	psf=mycalloc(aster->nwfs,dcell*);
	wvf=ccellnew(aster->nwfs,1);
	wvfc=ccellnew(aster->nwfs,1);
	mtche=mycalloc(aster->nwfs,dcell*);
	ints=mycalloc(aster->nwfs,dcell*);
	otf=ccellnew(aster->nwfs,1);
    
	for(long iwfs=0; iwfs<aster->nwfs; iwfs++){
	    const int ipowfs=aster->wfs[iwfs].ipowfs;
	    const long ncomp=parms->maos.ncomp[ipowfs];
	    const long nsa=parms->maos.nsa[ipowfs];
	    wvf->p[iwfs]=cnew(ncomp,ncomp);
	    wvfc->p[iwfs]=NULL;
	    psf[iwfs]=dcellnew(nsa,nwvl);
	    //cfft2plan(wvf->p[iwfs], -1);
	    if(parms->skyc.multirate){
		mtche[iwfs]=aster->wfs[iwfs].pistat->mtche[(int)aster->idtrats->p[iwfs]];
	    }else{
		mtche[iwfs]=aster->wfs[iwfs].pistat->mtche[idtratc];
	    }
	    otf->p[iwfs]=cnew(ncomp,ncomp);
	    //cfft2plan(otf->p[iwfs],-1);
	    //cfft2plan(otf->p[iwfs],1);
	    ints[iwfs]=dcellnew(nsa,1);
	    int pixpsa=parms->skyc.pixpsa[ipowfs];
	    for(long isa=0; isa<nsa; isa++){
		ints[iwfs]->p[isa]=dnew(pixpsa,pixpsa);
	    }
	}
    }
    for(int irep=0; irep<parms->skyc.navg; irep++){
	if(kalman){
	    kalman_init(kalman);
	}else{
	    servo_reset(st2t);
	}
	dcellzero(zgradc);
	dcellzero(gradout);
	if(ints){
	    for(int iwfs=0; iwfs<aster->nwfs; iwfs++){
		dcellzero(ints[iwfs]);
	    }
	}
	for(int istep=0; istep<nstep; istep++){
	    memcpy(merr->p, PCOL(mideal,istep), nmod*sizeof(double));
	    dadd(&merr, 1, mreal, -1);/*form NGS mode error; */
	    memcpy(PCOL(mres,istep),merr->p,sizeof(double)*nmod);
	    if(mpsol){//collect averaged modes for PSOL.
		for(long iwfs=0; iwfs<aster->nwfs; iwfs++){
		    dadd(&mpsol->p[iwfs], 1, mreal, 1);
		}
	    }
	    pmerrm=0;
	    if(istep>=parms->skyc.evlstart){/*performance evaluation*/
		double res_ngs=dwdot(merr->p,parms->maos.mcc,merr->p);
		if(res_ngs>ngsol*100){
		    dfree(res); res=NULL;
		    break;
		}
		{
		    res->p[0]+=res_ngs;
		    res->p[1]+=dwdot2(merr->p,parms->maos.mcc_tt,merr->p);
		    double dot_oa=dwdot(merr->p, parms->maos.mcc_oa, merr->p);
		    double dot_res_ideal=dwdot(merr->p, parms->maos.mcc_oa, PCOL(mideal,istep));
		    double dot_res_oa=0;
		    for(int imod=0; imod<nmod; imod++){
			dot_res_oa+=merr->p[imod]*IND(mideal_oa,imod,istep);
		    }
		    res->p[2]+=dot_oa-2*dot_res_ideal+2*dot_res_oa;
		    res->p[4]+=dot_oa;
		}
		{
		    double dot_oa_tt=dwdot2(merr->p, parms->maos.mcc_oa_tt, merr->p);
		    /*Notice that mcc_oa_tt2 is 2x5 marix. */
		    double dot_res_ideal_tt=dwdot(merr->p, parms->maos.mcc_oa_tt2, PCOL(mideal,istep));
		    double dot_res_oa_tt=0;
		    for(int imod=0; imod<2; imod++){
			dot_res_oa_tt+=merr->p[imod]*IND(mideal_oa,imod,istep);
		    }
		    res->p[3]+=dot_oa_tt-2*dot_res_ideal_tt+2*dot_res_oa_tt;
		    res->p[5]+=dot_oa_tt;
		}
	    }//if evl

	    if(istep<phystart || phystart<0){
		/*Ztilt, noise free simulation for acquisition. */
		dmm(&zgradc->m, 1, aster->gm, merr, "nn", 1);/*grad due to residual NGS mode. */
		for(int iwfs=0; iwfs<aster->nwfs; iwfs++){
		    const int ipowfs=aster->wfs[iwfs].ipowfs;
		    const long ng=parms->maos.nsa[ipowfs]*2;
		    for(long ig=0; ig<ng; ig++){
			zgradc->p[iwfs]->p[ig]+=aster->wfs[iwfs].ztiltout->p[istep*ng+ig];
		    }
		}
	
		for(int iwfs=0; iwfs<aster->nwfs; iwfs++){
		    int dtrati=(multirate?(int)dtrats->p[iwfs]:dtratc);
		    if((istep+1) % dtrati==0){
			dadd(&gradout->p[iwfs], 0, zgradc->p[iwfs], 1./dtrati);
			dzero(zgradc->p[iwfs]);
			if(noisy){
			    int idtrati=(multirate?(int)aster->idtrats->p[iwfs]:idtratc);
			    dmat *nea=aster->wfs[iwfs].pistat->sanea->p[idtrati];
			    for(int i=0; i<nea->nx; i++){
				gradout->p[iwfs]->p[i]+=nea->p[i]*randn(&aster->rand);
			    }
			}
			pmerrm=merrm;//record output.
		    }
		}
	    }else{
		/*Accumulate PSF intensities*/
		for(long iwfs=0; iwfs<aster->nwfs; iwfs++){
		    const double thetax=aster->wfs[iwfs].thetax;
		    const double thetay=aster->wfs[iwfs].thetay;
		    const int ipowfs=aster->wfs[iwfs].ipowfs;
		    const long nsa=parms->maos.nsa[ipowfs];
		    ccell* wvfout=aster->wfs[iwfs].wvfout[istep];
		    for(long iwvl=0; iwvl<nwvl; iwvl++){
			double wvl=parms->maos.wvl[iwvl];
			for(long isa=0; isa<nsa; isa++){
			    ccp(&wvfc->p[iwfs], IND(wvfout,isa,iwvl));
			    /*Apply NGS mode error to PSF. */
			    ngsmod2wvf(wvfc->p[iwfs], wvl, merr, powfs+ipowfs, isa,
				       thetax, thetay, parms);
			    cembedc(wvf->p[iwfs],wvfc->p[iwfs],0,C_FULL);
			    cfft2(wvf->p[iwfs],-1);
			    /*peak in corner. */
			    cabs22d(&psf[iwfs]->p[isa+nsa*iwvl], 1., wvf->p[iwfs], 1.);
			}/*isa */
		    }/*iwvl */
		}/*iwfs */
	
		/*Form detector image from accumulated PSFs*/
		double igrad[2];
		for(long iwfs=0; iwfs<aster->nwfs; iwfs++){
		    int dtrati=dtratc, idtrat=idtratc;
		    if(multirate){//multirate
			idtrat=aster->idtrats->p[iwfs];
			dtrati=dtrats->p[iwfs];
		    }
		    if((istep+1) % dtrati == 0){/*has output */
			dcellzero(ints[iwfs]);
			const int ipowfs=aster->wfs[iwfs].ipowfs;
			const long nsa=parms->maos.nsa[ipowfs];
			for(long isa=0; isa<nsa; isa++){
			    for(long iwvl=0; iwvl<nwvl; iwvl++){
				double siglev=aster->wfs[iwfs].siglev->p[iwvl];
				ccpd(&otf->p[iwfs],psf[iwfs]->p[isa+nsa*iwvl]);
				cfft2i(otf->p[iwfs], 1); /*turn to OTF, peak in corner */
				ccwm(otf->p[iwfs], powfs[ipowfs].dtf[iwvl].nominal);
				cfft2(otf->p[iwfs], -1);
				dspmulcreal(ints[iwfs]->p[isa]->p, powfs[ipowfs].dtf[iwvl].si, 
					   otf->p[iwfs]->p, siglev);
			    }
		
			    /*Add noise and apply matched filter. */
#if _OPENMP >= 200805 
#pragma omp critical 
#endif
			    switch(noisy){
			    case 0:/*no noise at all. */
				break;
			    case 1:/*both poisson and read out noise. */
				{
				    double bkgrnd=aster->wfs[iwfs].bkgrnd*dtrati;
				    addnoise(ints[iwfs]->p[isa], &aster->rand, bkgrnd, bkgrnd, 0,0,IND(rnefs,idtrat,ipowfs));
				}
				break;
			    case 2:/*there is still poisson noise. */
				addnoise(ints[iwfs]->p[isa], &aster->rand, 0, 0, 0,0,0);
				break;
			    default:
				error("Invalid noisy\n");
			    }
		
			    igrad[0]=0;
			    igrad[1]=0;
			    double pixtheta=parms->skyc.pixtheta[ipowfs];
			    if(parms->skyc.mtch){
				dmulvec(igrad, mtche[iwfs]->p[isa], ints[iwfs]->p[isa]->p, 1);
			    }
			    if(!parms->skyc.mtch || fabs(igrad[0])>pixtheta || fabs(igrad[1])>pixtheta){
				if(!parms->skyc.mtch){
				    warning2("fall back to cog\n");
				}else{
				    warning_once("mtch is out of range\n");
				}
				dcog(igrad, ints[iwfs]->p[isa], 0, 0, 0, 3*IND(rnefs,idtrat,ipowfs), 0); 
				igrad[0]*=pixtheta;
				igrad[1]*=pixtheta;
			    }
			    gradout->p[iwfs]->p[isa]=igrad[0];
			    gradout->p[iwfs]->p[isa+nsa]=igrad[1];
			}/*isa */
			pmerrm=merrm;
			dcellzero(psf[iwfs]);/*reset accumulation.*/
		    }/*if iwfs has output*/
		}/*for wfs*/
	    }/*if phystart */
	    //output to mreal after using it to ensure two cycle delay.
	    if(st2t){//Type I or II control.
		if(st2t->mint->p[0]){//has output.
		    dcp(&mreal, st2t->mint->p[0]->p[0]);
		}
	    }else{//LQG control
		kalman_output(kalman, &mreal, 0, 1);
	    }
	    if(kalman){//LQG control
		int indk=0;
		//Form PSOL grads and obtain index to LQG M
		for(int iwfs=0; iwfs<aster->nwfs; iwfs++){
		    int dtrati=(multirate?(int)dtrats->p[iwfs]:dtratc);
		    if((istep+1) % dtrati==0){
			indk|=1<<iwfs;
			dmm(&gradout->p[iwfs], 1, aster->g->p[iwfs], mpsol->p[iwfs], "nn", 1./dtrati);
			dzero(mpsol->p[iwfs]);
		    }
		}
		if(indk){
		    kalman_update(kalman, gradout->m, indk-1);
		}
	    }else if(st2t){
		if(pmerrm){
		    dmm(&merrm->p[0], 0, pgm, gradout->m, "nn", 1);	
		}
		servo_filter(st2t, pmerrm);//do even if merrm is zero. to simulate additional latency
	    }
	    if(parms->skyc.dbg){
		memcpy(PCOL(gradsave, istep), gradout->m->p, sizeof(double)*gradsave->nx);
	    }
	}/*istep; */
    }
    if(parms->skyc.dbg){
	int dtrati=(multirate?(int)dtrats->p[0]:dtratc);
	writebin(gradsave,"%s/skysim_grads_aster%d_dtrat%d",dirsetup, aster->iaster,dtrati);
	writebin(mres,"%s/skysim_sim_mres_aster%d_dtrat%d",dirsetup,aster->iaster,dtrati);
    }
  
    dfree(mreal);
    dcellfree(mpsol);
    dfree(merr);
    dcellfree(merrm);
    dcellfree(zgradc);
    dcellfree(gradout);
    dfree(gradsave);
    if(hasphy){
	dcellfreearr(psf, aster->nwfs);
	dcellfreearr(ints, aster->nwfs);
        ccellfree(wvf);
	ccellfree(wvfc);
	ccellfree(otf);
	free(mtche);
    }
    servo_free(st2t);
    /*dfree(mres); */
    if(mresout) {
	*mresout=mres;
    }else{
	dfree(mres);
    }
    dscale(res, 1./((nstep-parms->skyc.evlstart)*parms->skyc.navg));
    return res;
}
Beispiel #10
0
/**
   Open a port and listen to it. Calls respond(sock) to handle data. If
   timeout_fun is not NULL, it will be called when 1) connection is
   establed/handled, 2) every timeout_sec if timeout_sec>0. This function only
   return at error.
   if localpath is not null and start with /, open the local unix port also
   if localpath is not null and contains ip address, only bind to that ip address
 */
void listen_port(uint16_t port, char *localpath, int (*responder)(int),
		 double timeout_sec, void (*timeout_fun)(), int nodelay){
    register_signal_handler(scheduler_signal_handler);

    fd_set read_fd_set;
    fd_set active_fd_set;
    FD_ZERO (&active_fd_set);
    char *ip=0;
    int sock_local=-1;
    if(localpath){
	if(localpath[0]=='/'){
	    //also bind to AF_UNIX
	    sock_local = bind_socket_local(localpath);
	    if(sock_local==-1){
		info("bind to %s failed\n", localpath);
	    }else{
		if(!listen(sock_local, 1)){
		    FD_SET(sock_local, &active_fd_set);
		}else{
		    perror("listen");
		    close(sock_local);
		sock_local=-1;
		}
	    }
	}else{
	    ip=localpath;
	}
    }

    int sock = bind_socket (ip, port);
    if(nodelay){//turn off tcp caching.
	socket_tcp_nodelay(sock);
    }
    if (listen (sock, 1) < 0){
	perror("listen");
	exit(EXIT_FAILURE);
    }

    FD_SET (sock, &active_fd_set);
 
    while(quit_listen!=2){
	if(quit_listen==1){
	    /*
	      shutdown(sock, SHUT_WR) sends a FIN to the peer, therefore
	      initialize a active close and the port will remain in TIME_WAIT state.

	      shutdown(sock, SHUT_RD) sends nother, just mark the scoket as not readable.

	      accept() create a new socket on the existing port. A socket is identified by client ip/port and server ip/port.
	      
	      It is the port that remain in TIME_WAIT state.
	     */
	    //shutdown(sock, SHUT_RDWR);
	    //shutdown(sock_local, SHUT_RDWR);
	    /*Notice existing client to shutdown*/
	    for(int i=0; i<FD_SETSIZE; i++){
		if(FD_ISSET(i, &active_fd_set) && i!=sock && i!=sock_local){
		    int cmd[3]={-1, 0, 0};
		    stwrite(i, cmd, 3*sizeof(int)); //We ask the client to actively close the connection
		    //shutdown(i, SHUT_WR);
		}
	    }
	    usleep(1e5);
	    quit_listen=2;
	    //don't break. Listen for connection close events.
	}
	if(timeout_fun){
	    timeout_fun();
	}

	struct timeval timeout;
	timeout.tv_sec=timeout_sec;
	timeout.tv_usec=(timeout_sec-timeout.tv_sec)*1e6;
	read_fd_set = active_fd_set;
	if(select(FD_SETSIZE, &read_fd_set, NULL, NULL, &timeout)<0){
	    if(errno==EINTR){
		warning("select failed: %s\n", strerror(errno));
		continue;
	    }else if(errno==EBADF){
		warning("bad file descriptor: %s\n", strerror(errno));
		break;//bad file descriptor
	    }else{
		warning("unknown error: %s\n", strerror(errno));
		break;
	    }
	}
	for(int i=0; i<FD_SETSIZE; i++){
	    if(FD_ISSET(i, &read_fd_set)){
		if(i==sock){
		    /* Connection request on original socket. */
		    socklen_t size=sizeof(struct sockaddr_in);
		    struct sockaddr_in clientname;
    		    int port2=accept(i, (struct sockaddr*)&clientname, &size);
		    if(port2<0){
			warning("accept failed: %s. close port %d\n", strerror(errno), i);
			FD_CLR(i, &active_fd_set);
			close(i);
		    }else{
			info2("port %d is connected\n", port2);
			FD_SET(port2, &active_fd_set);
		    }
		}else if(i==sock_local){
		    socklen_t size=sizeof(struct sockaddr_un);
		    struct sockaddr_un clientname;
		    int port2=accept(i, (struct sockaddr*)&clientname, &size);
		    if(port2<0){
			warning("accept failed: %s. close port %d\n", strerror(errno), i);
			FD_CLR(i, &active_fd_set);
			close(i);
		    }else{
			info2("port %d is connected locally\n", port2);
			FD_SET(port2, &active_fd_set);
		    }
		}else{
		    /* Data arriving on an already-connected socket. Call responder to handle.
		       On return:
		       negative value: Close read of socket. 
		       -1: also close the socket.
		     */
		    int ans=responder(i);
		    if(ans<0){
			FD_CLR(i, &active_fd_set);
			if(ans==-1){
			    warning2("close port %d\n", i);
			    close(i);
			}else{
			    warning("ans=%d is not understood.\n", ans);
			}
		    }
		}
	    }
	}
    }
    /* Error happened. We close all connections and this server socket.*/
    close(sock);
    close(sock_local);
    FD_CLR(sock, &active_fd_set);
    FD_CLR(sock_local, &active_fd_set);
    warning("listen_port exited\n");
    for(int i=0; i<FD_SETSIZE; i++){
	if(FD_ISSET(i, &active_fd_set)){
	    warning("sock %d is still connected\n", i);
	    close(i);
	    FD_CLR(i, &active_fd_set);
	}
    }
    usleep(100);
    sync();
}