IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 18, 2010, 2:25:38 PM (16 years ago)
Author:
Paul Price
Message:

Discovered a race condition in the threading process. The thread process was: psThreadJobAlloc, populate job with arguments, psThreadJobAddPending, psFree the job. This is not thread-safe, because we're decrementing the job's reference counter while the reference count is also being fiddled within the thread system (psThread.c; by pulling the job off the 'pending' queue and putting it on the 'done' queue). The reference count fiddling within the thread system was protected by a mutex, but the external free was not. Therefore, I'm pulling the free into the thread system so it can be protected (without the user having to worry about locks to do the simple case). This means that the user should no longer touch the job once he hands it over to the thread system (unless it's protected by calls to psThreadLock/psThreadUnlock, or it's on the other side of psThreadPoolWait from all the adds so that the threads aren't doing anything).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psphot/src/psphotApResid.c

    r28013 r28405  
    2222    // loop over the available readouts
    2323    for (int i = 0; i < num; i++) {
    24         if (i == chisqNum) continue; // skip chisq image
    25         if (!psphotApResidReadout (config, view, filerule, i, recipe)) {
     24        if (i == chisqNum) continue; // skip chisq image
     25        if (!psphotApResidReadout (config, view, filerule, i, recipe)) {
    2626            psError (PSPHOT_ERR_CONFIG, false, "failed to measure aperture residual for %s entry %d", filerule, i);
    27             return false;
    28         }
     27            return false;
     28        }
    2929    }
    3030    return true;
     
    5656
    5757    if (!sources->n) {
    58         psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping ap resid");
    59         return true;
     58        psLogMsg ("psphot", PS_LOG_INFO, "no sources, skipping ap resid");
     59        return true;
    6060    }
    6161
     
    6666    int nThreads = psMetadataLookupS32(&status, config->arguments, "NTHREADS"); // Number of threads
    6767    if (!status) {
    68         nThreads = 0;
     68        nThreads = 0;
    6969    }
    7070
     
    128128    for (int i = 0; i < cellGroups->n; i++) {
    129129
    130         psArray *cells = cellGroups->data[i];
    131 
    132         for (int j = 0; j < cells->n; j++) {
    133 
    134             // allocate a job -- if threads are not defined, this just runs the job
    135             psThreadJob *job = psThreadJobAlloc ("PSPHOT_APRESID_MAGS");
    136 
    137             psArrayAdd(job->args, 1, cells->data[j]); // sources
    138             psArrayAdd(job->args, 1, psf);
    139             PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32);
    140             PS_ARRAY_ADD_SCALAR(job->args, maskVal,  PS_TYPE_IMAGE_MASK);
    141             PS_ARRAY_ADD_SCALAR(job->args, markVal,  PS_TYPE_IMAGE_MASK);
    142 
    143             PS_ARRAY_ADD_SCALAR(job->args, 0,        PS_TYPE_S32); // this is used as a return value for Nskip
    144             PS_ARRAY_ADD_SCALAR(job->args, 0,        PS_TYPE_S32); // this is used as a return value for Nfail
    145 
    146             if (!psThreadJobAddPending(job)) {
    147                 psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    148                 psFree (job);
    149                 return false;
    150             }
    151             psFree(job);
    152         }
    153 
    154         // wait for the threads to finish and manage results
    155         if (!psThreadPoolWait (false)) {
    156             psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
    157             return false;
    158         }
    159 
    160         // we have only supplied one type of job, so we can assume the types here
    161         psThreadJob *job = NULL;
    162         while ((job = psThreadJobGetDone()) != NULL) {
    163             if (job->args->n < 1) {
    164                 fprintf (stderr, "error with job\n");
    165             } else {
    166                 psScalar *scalar = NULL;
    167                 scalar = job->args->data[5];
    168                 Nskip += scalar->data.S32;
    169                 scalar = job->args->data[6];
    170                 Nfail += scalar->data.S32;
    171             }
    172             psFree(job);
    173         }
     130        psArray *cells = cellGroups->data[i];
     131
     132        for (int j = 0; j < cells->n; j++) {
     133
     134            // allocate a job -- if threads are not defined, this just runs the job
     135            psThreadJob *job = psThreadJobAlloc ("PSPHOT_APRESID_MAGS");
     136
     137            psArrayAdd(job->args, 1, cells->data[j]); // sources
     138            psArrayAdd(job->args, 1, psf);
     139            PS_ARRAY_ADD_SCALAR(job->args, photMode, PS_TYPE_S32);
     140            PS_ARRAY_ADD_SCALAR(job->args, maskVal,  PS_TYPE_IMAGE_MASK);
     141            PS_ARRAY_ADD_SCALAR(job->args, markVal,  PS_TYPE_IMAGE_MASK);
     142
     143            PS_ARRAY_ADD_SCALAR(job->args, 0,        PS_TYPE_S32); // this is used as a return value for Nskip
     144            PS_ARRAY_ADD_SCALAR(job->args, 0,        PS_TYPE_S32); // this is used as a return value for Nfail
     145
     146            if (!psThreadJobAddPending(job)) {
     147                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     148                return false;
     149            }
     150        }
     151
     152        // wait for the threads to finish and manage results
     153        if (!psThreadPoolWait (false)) {
     154            psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     155            return false;
     156        }
     157
     158        // we have only supplied one type of job, so we can assume the types here
     159        psThreadJob *job = NULL;
     160        while ((job = psThreadJobGetDone()) != NULL) {
     161            if (job->args->n < 1) {
     162                fprintf (stderr, "error with job\n");
     163            } else {
     164                psScalar *scalar = NULL;
     165                scalar = job->args->data[5];
     166                Nskip += scalar->data.S32;
     167                scalar = job->args->data[6];
     168                Nfail += scalar->data.S32;
     169            }
     170            psFree(job);
     171        }
    174172    }
    175173
     
    184182    Npsf = 0;
    185183
    186 # ifdef DEBUG   
     184# ifdef DEBUG
    187185    FILE *f = fopen ("apresid.dat", "w");
    188186    psAssert (f, "failed open");
     
    199197        if (source->mode &  PM_SOURCE_MODE_POOR) SKIPSTAR ("POOR STAR");
    200198
    201         if (source->mode &  PM_SOURCE_MODE_EXT_LIMIT) SKIPSTAR ("EXTENDED");
    202         if (source->mode &  PM_SOURCE_MODE_CR_LIMIT) SKIPSTAR ("COSMIC RAY");
    203         if (source->mode &  PM_SOURCE_MODE_DEFECT) SKIPSTAR ("DEFECT");
    204            
     199        if (source->mode &  PM_SOURCE_MODE_EXT_LIMIT) SKIPSTAR ("EXTENDED");
     200        if (source->mode &  PM_SOURCE_MODE_CR_LIMIT) SKIPSTAR ("COSMIC RAY");
     201        if (source->mode &  PM_SOURCE_MODE_DEFECT) SKIPSTAR ("DEFECT");
     202
    205203        if (!isfinite(source->apMag) || !isfinite(source->psfMag)) {
    206204            continue;
    207205        }
    208206
    209         // XXX make this user-configurable?
    210         if (source->errMag > 0.01) continue;
     207        // XXX make this user-configurable?
     208        if (source->errMag > 0.01) continue;
    211209
    212210        // aperture residual for this source
     
    221219
    222220# ifdef DEBUG
    223         fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f\n",
    224                  source->peak->xf, source->peak->yf,
    225                  source->modelPSF->params->data.F32[PM_PAR_XPOS], source->modelPSF->params->data.F32[PM_PAR_YPOS],
    226                 source->psfMag, source->apMag, source->errMag,
    227                  source->modelPSF->params->data.F32[PM_PAR_I0],
    228                  source->modelPSF->params->data.F32[PM_PAR_SXX], source->modelPSF->params->data.F32[PM_PAR_SXY], source->modelPSF->params->data.F32[PM_PAR_SYY],
    229                 source->modelPSF->params->data.F32[PM_PAR_7]);
     221        fprintf (f, "%6.1f %6.1f : %6.1f %6.1f : %8.3f %8.3f %8.3f : %f : %f %f %f : %f\n",
     222                 source->peak->xf, source->peak->yf,
     223                 source->modelPSF->params->data.F32[PM_PAR_XPOS], source->modelPSF->params->data.F32[PM_PAR_YPOS],
     224                source->psfMag, source->apMag, source->errMag,
     225                 source->modelPSF->params->data.F32[PM_PAR_I0],
     226                 source->modelPSF->params->data.F32[PM_PAR_SXX], source->modelPSF->params->data.F32[PM_PAR_SXY], source->modelPSF->params->data.F32[PM_PAR_SYY],
     227                source->modelPSF->params->data.F32[PM_PAR_7]);
    230228# endif
    231         if (!isfinite(source->psfMag)) psAbort ("nan in psfMag");
    232         if (!isfinite(source->errMag)) psAbort ("nan in errMag");
    233         if (!isfinite(source->apMag)) psAbort ("nan in apMag");
    234         if (!isfinite(model->params->data.F32[PM_PAR_XPOS])) psAbort ("nan in xPos");
    235         if (!isfinite(model->params->data.F32[PM_PAR_YPOS])) psAbort ("nan in yPos");
     229        if (!isfinite(source->psfMag)) psAbort ("nan in psfMag");
     230        if (!isfinite(source->errMag)) psAbort ("nan in errMag");
     231        if (!isfinite(source->apMag)) psAbort ("nan in apMag");
     232        if (!isfinite(model->params->data.F32[PM_PAR_XPOS])) psAbort ("nan in xPos");
     233        if (!isfinite(model->params->data.F32[PM_PAR_YPOS])) psAbort ("nan in yPos");
    236234
    237235        psVectorAppend (mag, source->psfMag);
     
    253251    if (Npsf < APTREND_NSTAR_MIN) {
    254252        psWarning("Only %d valid aperture residual sources (need %d), giving up", Npsf, APTREND_NSTAR_MIN);
    255         goto escape;
    256     }
    257 
    258     // this is a bit tricky, because we have two cases (MAP vs POLY), and they have a different 
    259     // definition for 'order' (order_MAP = order_POLY + 1).  in addition, we have a 
     253        goto escape;
     254    }
     255
     256    // this is a bit tricky, because we have two cases (MAP vs POLY), and they have a different
     257    // definition for 'order' (order_MAP = order_POLY + 1).  in addition, we have a
    260258    // user-specified MAX order, which we should respect, regardless of the mode
    261259
     
    270268    pmTrend2DMode mode = PM_TREND_MAP;
    271269    if (mode == PM_TREND_MAP) {
    272         MaxOrderForStars ++;
    273     } 
     270        MaxOrderForStars ++;
     271    }
    274272    APTREND_ORDER_MAX = PS_MIN (APTREND_ORDER_MAX, MaxOrderForStars);
    275273
     
    283281    int NY = readout->image->numRows;
    284282    for (int i = 1; i <= APTREND_ORDER_MAX; i++) {
    285        
    286         int Nx, Ny;
    287         if (NX > NY) {
    288             Nx = i;
    289             Ny = PS_MAX (1, (int)(i * (NY / (float)(NX)) + 0.5));
    290         } else {
    291             Ny = i;
    292             Nx = PS_MAX (1, (int)(i * (NX / (float)(NY)) + 0.5));
    293         }
    294 
    295         float errorFloor;
     283
     284        int Nx, Ny;
     285        if (NX > NY) {
     286            Nx = i;
     287            Ny = PS_MAX (1, (int)(i * (NY / (float)(NX)) + 0.5));
     288        } else {
     289            Ny = i;
     290            Nx = PS_MAX (1, (int)(i * (NX / (float)(NY)) + 0.5));
     291        }
     292
     293        float errorFloor;
    296294        pmTrend2D *apTrend = psphotApResidTrend (&errorFloor, readout, Nx, Ny, xPos, yPos, apResid, dMag);
    297         if (!apTrend) {
    298             continue;
    299         }
    300 
    301         // apply ApTrend results
    302         // float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5;
    303         // float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5;
    304         // float ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center
    305         // if (!isfinite(ApResid)) psAbort("nan apresid @ center");
     295        if (!apTrend) {
     296            continue;
     297        }
     298
     299        // apply ApTrend results
     300        // float xc = 0.5*readout->image->numCols + readout->image->col0 + 0.5;
     301        // float yc = 0.5*readout->image->numRows + readout->image->row0 + 0.5;
     302        // float ApResid = pmTrend2DEval (psf->ApTrend, xc, yc); // ap-fit at chip center
     303        // if (!isfinite(ApResid)) psAbort("nan apresid @ center");
    306304
    307305        // store the minimum errorFloor and best ApTrend to keep
    308306        if (errorFloor < errorFloorMin) {
    309307            errorFloorMin = errorFloor;
    310             psFree (psf->ApTrend);
    311             psf->ApTrend = psMemIncrRefCounter(apTrend);
    312         }
    313         psFree (apTrend);
     308            psFree (psf->ApTrend);
     309            psf->ApTrend = psMemIncrRefCounter(apTrend);
     310        }
     311        psFree (apTrend);
    314312    }
    315313    if (psf->ApTrend == NULL) {
    316314        psWarning("Failed to find a valid aperture residual value");
    317         goto escape;
     315        goto escape;
    318316    }
    319317
     
    383381    if (!pmTrend2DFit (apTrend, mask, 0xff, xPos, yPos, apResid, dMagSoft)) {
    384382        psWarning("Failed to fit trend for %d x %d map", Nx, Ny);
    385         psFree (apTrend);
    386         return NULL;
     383        psFree (apTrend);
     384        return NULL;
    387385    }
    388386    if (apTrend->mode == PM_TREND_MAP) {
    389         // p_psImagePrint (2, apTrend->map->map, "ApTrend Before"); // XXX TEST:
    390         psImageMapRepair (apTrend->map->map);
    391         // p_psImagePrint (2, apTrend->map->map, "ApTrend After"); // XXX TEST:
     387        // p_psImagePrint (2, apTrend->map->map, "ApTrend Before"); // XXX TEST:
     388        psImageMapRepair (apTrend->map->map);
     389        // p_psImagePrint (2, apTrend->map->map, "ApTrend After"); // XXX TEST:
    392390    }
    393391
     
    400398    if (!isfinite(*apResidSysErr)) {
    401399        psWarning("Failed to find systematic error for %d x %d map", Nx, Ny);
    402         psFree (apTrend);
    403         return NULL;
     400        psFree (apTrend);
     401        return NULL;
    404402    }
    405403
     
    408406
    409407    if (psTraceGetLevel("psphot") >= 4) {
    410         char filename[64];
    411         snprintf (filename, 64, "apresid.%dx%d.dat", Nx, Ny);
     408        char filename[64];
     409        snprintf (filename, 64, "apresid.%dx%d.dat", Nx, Ny);
    412410        FILE *dumpFile = fopen (filename, "w");
    413411        for (int i = 0; i < xPos->n; i++) {
     
    457455        }
    458456
    459         // clear the mask bit and set the circular mask pixels
    460         psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
    461         psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal);
    462 
    463         bool status = pmSourceMagnitudes (source, psf, photMode, maskVal);
    464 
    465         // clear the mask bit
    466         psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
     457        // clear the mask bit and set the circular mask pixels
     458        psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
     459        psImageKeepCircle (source->maskObj, source->peak->x, source->peak->y, source->apRadius, "OR", markVal);
     460
     461        bool status = pmSourceMagnitudes (source, psf, photMode, maskVal);
     462
     463        // clear the mask bit
     464        psImageMaskPixels (source->maskObj, "AND", PS_NOT_IMAGE_MASK(markVal));
    467465
    468466        // re-subtract the object, leave local sky
    469467        pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    470468
    471         if (!status) {
    472             Nskip ++;
    473             psTrace ("psphot", 3, "skip : bad source mag");
    474             continue;
    475         }
    476    
    477         if (!isfinite(source->apMag) || !isfinite(source->psfMag)) {
    478             Nfail ++;
    479             psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag);
    480             continue;
    481         }
    482         source->mode |= PM_SOURCE_MODE_AP_MAGS;
     469        if (!status) {
     470            Nskip ++;
     471            psTrace ("psphot", 3, "skip : bad source mag");
     472            continue;
     473        }
     474
     475        if (!isfinite(source->apMag) || !isfinite(source->psfMag)) {
     476            Nfail ++;
     477            psTrace ("psphot", 3, "fail : nan mags : %f %f", source->apMag, source->psfMag);
     478            continue;
     479        }
     480        source->mode |= PM_SOURCE_MODE_AP_MAGS;
    483481    }
    484482
Note: See TracChangeset for help on using the changeset viewer.