IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 28405 for trunk/psLib


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).

Location:
trunk/psLib/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/imageops/psImageConvolve.c

    r28136 r28405  
    864864            PS_ARRAY_ADD_SCALAR(job->args, stop, PS_TYPE_S32);
    865865            if (!psThreadJobAddPending(job)) {
    866                 psFree(job);
    867866                psFree(gaussNorm);
    868867                psFree(out);
    869868                return NULL;
    870869            }
    871             psFree(job);
    872870        }
    873871        if (!psThreadPoolWait(true)) {
     
    12131211                  if (!psThreadJobAddPending(job)) {
    12141212                      psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
    1215                       psFree(job);
    12161213                      psFree(calculation);
    12171214                      psFree(calcMask);
     
    12191216                      return false;
    12201217                  }
    1221                   psFree(job);
    12221218              }
    12231219              // wait here for the threaded jobs to finish (NOP if threading is not active)
     
    12611257                  if (!psThreadJobAddPending(job)) {
    12621258                      psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
    1263                       psFree(job);
    12641259                      psFree(calculation);
    12651260                      psFree(calcMask);
     
    12671262                      return false;
    12681263                  }
    1269                   psFree(job);
    12701264              }
    12711265
     
    15801574            PS_ARRAY_ADD_SCALAR(job->args, 0x00, PS_TYPE_U8); // specify rows
    15811575            if (!psThreadJobAddPending(job)) {
    1582                 psFree(job);
    15831576                psFree(conv);
    15841577                psFree(out);
    15851578                return NULL;
    15861579            }
    1587             psFree(job);
    15881580        }
    15891581        if (!psThreadPoolWait(true)) {
     
    16171609            PS_ARRAY_ADD_SCALAR(job->args, 0xff, PS_TYPE_U8); // specify cols
    16181610            if (!psThreadJobAddPending(job)) {
    1619                 psFree(job);
    16201611                psFree(conv);
    16211612                psFree(out);
    16221613                return NULL;
    16231614            }
    1624             psFree(job);
    16251615        }
    16261616        if (!psThreadPoolWait(true)) {
  • trunk/psLib/src/imageops/psImageCovariance.c

    r28152 r28405  
    169169                    return NULL;
    170170                }
    171                 psFree(job);
    172171            } else {
    173172                out->kernel[y][x] = imageCovarianceCalculate(covar, kernel, x, y);
     
    334333                    return NULL;
    335334                }
    336                 psFree(job);
    337335            } else {
    338336                out->kernel[y][x] = imageCovarianceBin(covar, bin, binVal, x, y);
  • trunk/psLib/src/sys/psThread.c

    r28402 r28405  
    9999bool psThreadJobAddPending(psThreadJob *job)
    100100{
    101     PS_ASSERT_THREAD_JOB_NON_NULL(job, false);
     101    if (!job) {
     102        // Asking for a no-op
     103        return true;
     104    }
    102105
    103106    psThreadTask *task = psHashLookup(tasks, job->type); // Task to execute job
     
    114117        }
    115118        psListAdd(done, PS_LIST_TAIL, job);
    116 
     119        psFree(job);
    117120        return task->function(job);
    118121    }
     
    123126    }
    124127    psListAdd(pending, PS_LIST_TAIL, job);
     128    psFree(job);
    125129    psThreadUnlock();
    126130
     
    279283    for (int i = 0; i < nThreads; i++) {
    280284        psThread *thread = pool->data[i] = psThreadAlloc(); // Thread for pool
    281         if (!pthread_create(&threads[i], NULL, psThreadLauncher, thread)) {
     285        if (pthread_create(&threads[i], NULL, psThreadLauncher, thread)) {
    282286            psAbort("Unable to create thread");
    283287        }
  • trunk/psLib/src/sys/psThread.h

    r28402 r28405  
    7373
    7474/// Add a pending job to the queue
     75///
     76/// This function swallows the provided job, so that the user no longer owns it.  This is because freeing the
     77/// job is not thread-safe (its reference count is being changed within the threads) so we handle it ourselves
     78/// and absolve the user from all responsibility.  If the user stores the job, he should only access it while
     79/// threads are processing in code protected by psThreadLock/psThreadUnlock.
    7580bool psThreadJobAddPending(psThreadJob *job);
    7681
    7782/// Get a job off the queue of pending jobs
     83///
     84/// This function is not thread-safe.  Protect with psThreadLock/psThreadUnlock if threads are running.
    7885psThreadJob *psThreadJobGetPending(void);
    7986
    8087/// Get a job off the queue of done jobs
     88///
     89/// This function is not thread-safe.  Protect with psThreadLock/psThreadUnlock if threads are running.
    8190psThreadJob *psThreadJobGetDone(void);
    8291
     
    115124bool psThreadPoolFinalize(void);
    116125
    117 
     126#if 0
    118127/// Add thread-specific data
    119128///
     
    134143bool psThreadDataRemove(const char *name // Name of data
    135144    );
    136 
     145#endif
    137146
    138147/// @}
Note: See TracChangeset for help on using the changeset viewer.