square / pylink

Python Library for device debugging/programming via J-Link
https://pylink.readthedocs.io/en/latest/
Other
334 stars 125 forks source link

WinARM64 - The temporary copy of library is not deleted when Library object is released. #173

Closed vovabvp closed 11 months ago

vovabvp commented 1 year ago

Hello,

Looks like it's the same issue as #166. But in my case I, probably, need to keep the library because I'm using several j-links connected to my PC, And during debug process I have connected same j-link to python-script and Keil uVision.

I'm using pylink to program few devices and collect the data from them in parallel. Everything was working fine under the Windows11-x64 and Python-3.10.10-x64 that is in Virtual machine on Intel based MacBook. But I'm getting next error on Windows11-ARM64 and Python-3.10.10-x64 that is in Virtual machine on M2 based MacBook:

Exception ignored in: <function Library.del at 0x0000027ECCF10940> Traceback (most recent call last): File "C:\Python310\lib\site-packages\pylink\library.py", line 302, in del self.unload() File "C:\Python310\lib\site-packages\pylink\library.py", line 461, in unload os.remove(self._temp.name) PermissionError: [WinError 5] Access is denied: 'C:\Users\VOLODY~1\AppData\Local\Temp\tmpk0gnks6r.dll'

Should I provide any additional information?

Thanks.

vovabvp commented 1 year ago

I'm not expert in python but here is some observations. Error reproducible by two methods: first method:

>>> import pylink
>>> jlink = pylink.JLink()
>>> jlink = pylink.JLink()

second method:

>>> import pylink
>>> jlink = pylink.JLink()
>>> exit()

In both cases PermissionError is reproducible and new *.dll file is left undeleted in the Temp folder.

First method could be fixed by adding 0.5s delay before the *.dll file removal in "..\site-packages\pylink\library.py"

460:        if self._temp is not None:
461:            time.sleep(0.5)
462:            os.remove(self._temp.name)
463:            self._temp = None

But adding delay is not helpful for the second method, because delay is ignored.

vovabvp commented 1 year ago

Did some debugging of the issue. Code below shows that something is holding *.dll and preventing from deleting. When cpu is not busy it takes about 250-350 attempts to delete a file. In case CPU is loaded this number could be increased a lot and 1000 attempts will not be enough.

460:        if self._temp is not None:
461:            i = 0
462:            while os.path.isfile(self._temp.name):
463:                i += 1
464:                if i > 1000: break
465:                try:
466:                    os.remove(self._temp.name)
467:                except PermissionError:
468:                    pass
469:            print(i)
470:            self._temp = None
hkpeprah commented 1 year ago

172 has a workaround for this which should be available in v1.1.0.

vovabvp commented 1 year ago

Hi, Thanks for workaround, it works as expected. But what the limitation of this workaround? Thanks.

hkpeprah commented 1 year ago

Hi, Thanks for workaround, it works as expected. But what the limitation of this workaround? Thanks.

In older versions of the SDK, multiple instances of the JLink instance couldn't be used at the same time because the SDK had an issue with locking exclusive access of a device. The workaround addressed this by copying the library file, preventing the lock issue from occurring. If you're using a new version of the SDK (>= 6), you shouldn't have an issue.

vovabvp commented 11 months ago

Thanks for explanation. Tested with my usage cases and issue is not observed anymore.