new_contents: from base import DjangCronJobLock
  
  from django.conf import settings
  from django.core.files import locks
  import os, sys, errno
  
  class FileLock(DjangCronJobLock):
      """
      Quite a simple lock backend that uses some kind of pid file.
      """
  
      def lock(self):
          try:
              lock_name = self.get_lock_name()
              # need loop to avoid races on file unlinking
              while True:
                  f = open(lock_name, 'w+', 0)
                  locks.lock(f, locks.LOCK_EX | locks.LOCK_NB)
  # Here is the Race:
  # Previous process "A" is still running. Process "B" opens
  # the file and then the process "A" finishes and deletes it.
  # "B" locks the deleted file (by fd it already have) and runs,
  # then the next process "C" creates _new_ file and locks it
  # successfully while "B" is still running.
  # We just need to check that "B" didn't lock a deleted file
  # to avoid any problems. If process "C" have locked
  # a new file wile "B" stats it then ok, let "B" quit and "C" run.
  # We can still meet an attacker that permanently creates and deletes
  # our file but we can't avoid problems in that case.
                  if os.path.isfile(lock_name):
                      st1 = os.fstat(f.fileno())
                      st2 = os.stat(lock_name)
                      if st1.st_ino == st2.st_ino:
                          f.write( str(os.getpid()) )
                          self.lockfile = f
                          return True
                  #else:
                  # retry. Don't unlink, next process might already use it.
                  f.close()
  
          except IOError as e:
              if e.errno in (errno.EACCES, errno.EAGAIN):
                  self.notice_lock_failed()
                  return False
              else:
                  t, v, tb = sys.exc_info()
                  raise t, v, tb
  
      def release(self):
          f = self.lockfile
          # unlink before release lock to avoid race
          # see comment in self.lock for description
          os.unlink(f.name)
          f.close()
  
      def get_lock_name(self):
          default_path = '/tmp'
          path = getattr(settings, 'DJANGO_CRON_LOCKFILE_PATH', default_path)
          if not os.path.isdir(path):
              # let it die if failed, can't run further anyway
              os.makedirs(path)
  
          filename = self.job_name + '.lock'
          return os.path.join(path, filename)
  
subject: add file lock backend that uses lockfiles to prevent paralle run of cron job