예제 #1
0
    def _testAsynchronousLockWait(self):
        scheduler = global_event_loop()
        tempdir = tempfile.mkdtemp()
        try:
            path = os.path.join(tempdir, 'lock_me')
            lock1 = AsynchronousLock(path=path, scheduler=scheduler)
            scheduler.run_until_complete(lock1.async_start())
            self.assertEqual(lock1.wait(), os.EX_OK)
            self.assertEqual(lock1.returncode, os.EX_OK)

            # lock2 requires _force_async=True since the portage.locks
            # module is not designed to work as intended here if the
            # same process tries to lock the same file more than
            # one time concurrently.
            lock2 = AsynchronousLock(path=path,
                                     scheduler=scheduler,
                                     _force_async=True,
                                     _force_process=True)
            scheduler.run_until_complete(lock2.async_start())
            # lock2 should be waiting for lock1 to release
            self.assertEqual(lock2.poll(), None)
            self.assertEqual(lock2.returncode, None)

            scheduler.run_until_complete(lock1.async_unlock())
            self.assertEqual(lock2.wait(), os.EX_OK)
            self.assertEqual(lock2.returncode, os.EX_OK)
            scheduler.run_until_complete(lock2.async_unlock())
        finally:
            shutil.rmtree(tempdir)
예제 #2
0
    def _testAsynchronousLock(self):
        scheduler = global_event_loop()
        tempdir = tempfile.mkdtemp()
        try:
            path = os.path.join(tempdir, 'lock_me')
            for force_async in (True, False):
                for force_dummy in ((False, ) if dummy_threading is None else
                                    (True, False)):
                    async_lock = AsynchronousLock(path=path,
                                                  scheduler=scheduler,
                                                  _force_async=force_async,
                                                  _force_thread=True,
                                                  _force_dummy=force_dummy)
                    scheduler.run_until_complete(async_lock.async_start())
                    self.assertEqual(async_lock.wait(), os.EX_OK)
                    self.assertEqual(async_lock.returncode, os.EX_OK)
                    scheduler.run_until_complete(async_lock.async_unlock())

                async_lock = AsynchronousLock(path=path,
                                              scheduler=scheduler,
                                              _force_async=force_async,
                                              _force_process=True)
                scheduler.run_until_complete(async_lock.async_start())
                self.assertEqual(async_lock.wait(), os.EX_OK)
                self.assertEqual(async_lock.returncode, os.EX_OK)
                scheduler.run_until_complete(async_lock.async_unlock())
        finally:
            shutil.rmtree(tempdir)
예제 #3
0
    def _testAsynchronousLockWaitKill(self):
        scheduler = global_event_loop()
        tempdir = tempfile.mkdtemp()
        try:
            path = os.path.join(tempdir, 'lock_me')
            lock1 = AsynchronousLock(path=path, scheduler=scheduler)
            scheduler.run_until_complete(lock1.async_start())
            self.assertEqual(lock1.wait(), os.EX_OK)
            self.assertEqual(lock1.returncode, os.EX_OK)
            lock2 = AsynchronousLock(path=path,
                                     scheduler=scheduler,
                                     _force_async=True,
                                     _force_process=True)
            scheduler.run_until_complete(lock2.async_start())
            # lock2 should be waiting for lock1 to release
            self.assertEqual(lock2.poll(), None)
            self.assertEqual(lock2.returncode, None)

            # Kill lock2's process and then check wait() and
            # returncode results. This is intended to simulate
            # a SIGINT sent via the controlling tty.
            self.assertEqual(lock2._imp is not None, True)
            self.assertEqual(lock2._imp._proc is not None, True)
            self.assertEqual(lock2._imp._proc.pid is not None, True)
            lock2._imp._kill_test = True
            os.kill(lock2._imp._proc.pid, signal.SIGTERM)
            self.assertEqual(lock2.wait() == os.EX_OK, False)
            self.assertEqual(lock2.returncode == os.EX_OK, False)
            self.assertEqual(lock2.returncode is None, False)
            scheduler.run_until_complete(lock1.async_unlock())
        finally:
            shutil.rmtree(tempdir)
예제 #4
0
    def _testAsynchronousLockWaitCancel(self):
        scheduler = global_event_loop()
        tempdir = tempfile.mkdtemp()
        try:
            path = os.path.join(tempdir, 'lock_me')
            lock1 = AsynchronousLock(path=path, scheduler=scheduler)
            scheduler.run_until_complete(lock1.async_start())
            self.assertEqual(lock1.wait(), os.EX_OK)
            self.assertEqual(lock1.returncode, os.EX_OK)
            lock2 = AsynchronousLock(path=path,
                                     scheduler=scheduler,
                                     _force_async=True,
                                     _force_process=True)
            scheduler.run_until_complete(lock2.async_start())
            # lock2 should be waiting for lock1 to release
            self.assertEqual(lock2.poll(), None)
            self.assertEqual(lock2.returncode, None)

            # Cancel lock2 and then check wait() and returncode results.
            lock2.cancel()
            self.assertEqual(lock2.wait() == os.EX_OK, False)
            self.assertEqual(lock2.returncode == os.EX_OK, False)
            self.assertEqual(lock2.returncode is None, False)
            scheduler.run_until_complete(lock1.async_unlock())
        finally:
            shutil.rmtree(tempdir)
예제 #5
0
    def async_unlock(self):
        """
		Release the lock asynchronously. Release notification is available
		via the add_done_callback method of the returned Future instance.

		@returns: Future, result is None
		"""
        if self._lock_obj is not None:
            yield self._lock_obj.async_unlock()

            self._lock_obj = None
            self.locked = False
            self.settings.pop('PORTAGE_BUILDDIR_LOCKED', None)
            catdir_lock = AsynchronousLock(path=self._catdir,
                                           scheduler=self.scheduler)
            try:
                yield catdir_lock.async_start()
                yield catdir_lock.async_wait()
            except asyncio.CancelledError:
                if catdir_lock.poll() is None:
                    catdir_lock.cancel()
                raise

            if catdir_lock.returncode == os.EX_OK:
                try:
                    os.rmdir(self._catdir)
                except OSError:
                    pass
                yield catdir_lock.async_unlock()
예제 #6
0
    def async_lock(self):
        """
		Acquire the lock asynchronously. Notification is available
		via the add_done_callback method of the returned Future instance.

		This raises an AlreadyLocked exception if async_lock() is called
		while a lock is already held. In order to avoid this, call
		async_unlock() or check whether the "locked" attribute is True
		or False before calling async_lock().

		@returns: Future, result is None
		"""
        if self._lock_obj is not None:
            raise self.AlreadyLocked((self._lock_obj, ))

        dir_path = self.settings.get('PORTAGE_BUILDDIR')
        if not dir_path:
            raise AssertionError('PORTAGE_BUILDDIR is unset')
        catdir = os.path.dirname(dir_path)
        self._catdir = catdir

        try:
            portage.util.ensure_dirs(os.path.dirname(catdir),
                                     gid=portage.portage_gid,
                                     mode=0o70,
                                     mask=0)
        except PortageException:
            if not os.path.isdir(os.path.dirname(catdir)):
                raise

        catdir_lock = AsynchronousLock(path=catdir, scheduler=self.scheduler)
        builddir_lock = AsynchronousLock(path=dir_path,
                                         scheduler=self.scheduler)
        try:
            yield catdir_lock.async_start()
            yield catdir_lock.async_wait()

            self._assert_lock(catdir_lock)

            try:
                portage.util.ensure_dirs(catdir,
                                         gid=portage.portage_gid,
                                         mode=0o70,
                                         mask=0)
            except PortageException:
                if not os.path.isdir(catdir):
                    raise

            yield builddir_lock.async_start()
            yield builddir_lock.async_wait()
        except asyncio.CancelledError:
            if catdir_lock.poll() is None:
                catdir_lock.cancel()
            if builddir_lock.poll() is None:
                builddir_lock.cancel()
            raise

        try:
            self._assert_lock(builddir_lock)
        except AssertionError:
            yield catdir_lock.async_unlock()
            raise

        self._lock_obj = builddir_lock
        self.locked = True
        self.settings['PORTAGE_BUILDDIR_LOCKED'] = '1'
        yield catdir_lock.async_unlock()