[issue25241] ctypes: access violation reading

2015-09-26 Thread Dum Dum

New submission from Dum Dum:

On Windows 8.1 64-bit, using a fresh installation of Python 3.5.150.0 64-bit, 
`error_script.py` crashes, while Python 3.4.3150 and 2.7.10150 (both 64-bit) 
run the script properly.

Here is a traceback: https://bpaste.net/show/3ecfbf93b96e

--
files: error_script.py
messages: 251658
nosy: Dum.Dum
priority: normal
severity: normal
status: open
title: ctypes: access violation reading
type: crash
versions: Python 3.5
Added file: http://bugs.python.org/file40589/error_script.py

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25241] ctypes: access violation reading

2015-09-26 Thread Dum Dum

Dum Dum added the comment:

I rewrote the code following your suggestions and it appears the error was 
indeed on my side. I somewhat expected that, but found it weird that it only 
seemed to occur on 3.5. Thank you!

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25241] ctypes: access violation reading

2015-09-26 Thread eryksun

eryksun added the comment:

The default function pointer restype is c_int, and the default integer argument 
conversion is also c_int. However, the handle returned by FindFirstVolume is a 
pointer to a private structure that it uses for the volume enumeration, so you 
must set restype to a pointer type. Similarly, if restype is a simple type that 
gets converted to a Python integer (e.g. wintypes.HANDLE), then you must either 
set FindNextVolumeW.argtypes or manually wrap the handle value (e.g. vhandle = 
wintypes.HANDLE(vhandle)). The default c_int conversions will only work if the 
address happens to fit in a 32-bit int. 

Don't forget to call FindVolumeClose if the process is expected to continue. 
Otherwise you're leaking memory.

Also, if you're defining function pointer prototypes for a library, please do 
not use ctypes.cdll or ctypes.windll. The loaders are global to ctypes and by 
design cache the loaded library, which by design caches function pointers. 
Projects such as pyreadline and colorama have demonstrated the problems that 
this creates due to inconsistent prototype definitions, especially for commonly 
used Win32 APIs.

Here is one way to rewrite your code to have it work more reliably:

import ctypes
from ctypes import wintypes

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

kernel32.FindFirstVolumeW.restype = wintypes.HANDLE
kernel32.FindNextVolumeW.argtypes = (wintypes.HANDLE,
 wintypes.LPWSTR,
 wintypes.DWORD)
kernel32.FindVolumeClose.argtypes = (wintypes.HANDLE,)

INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
ERROR_NO_MORE_FILES = 18

def list_volumes():
vname = ctypes.create_unicode_buffer(wintypes.MAX_PATH)
vhandle = kernel32.FindFirstVolumeW(vname, len(vname))
if vhandle == INVALID_HANDLE_VALUE:
raise ctypes.WinError(ctypes.get_last_error())
volumes = []
try:
while True:
volumes.append(vname.value)
if not kernel32.FindNextVolumeW(vhandle, vname, len(vname)):
last_error = ctypes.get_last_error()
if last_error == ERROR_NO_MORE_FILES:
break
else:
raise ctypes.WinError(last_error)
finally:
if not kernel32.FindVolumeClose(vhandle):
raise ctypes.WinError(ctypes.get_last_error())
return volumes

if __name__ == '__main__':
for volume in list_volumes():
print(volume)

--
nosy: +eryksun
resolution:  -> not a bug
stage:  -> resolved
status: open -> closed

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25241] ctypes: access violation reading

2015-09-26 Thread eryksun

eryksun added the comment:

Here's a rewrite with a cleaner while loop, at least to me:

def list_volumes():
vname = ctypes.create_unicode_buffer(wintypes.MAX_PATH)
vhandle = kernel32.FindFirstVolumeW(vname, len(vname))
if vhandle == INVALID_HANDLE_VALUE:
raise ctypes.WinError(ctypes.get_last_error())
volumes = [vname.value]
try:
while kernel32.FindNextVolumeW(vhandle, vname, len(vname)):
volumes.append(vname.value)
last_error = ctypes.get_last_error()
if last_error != ERROR_NO_MORE_FILES:
raise ctypes.WinError(last_error)
finally:
if not kernel32.FindVolumeClose(vhandle):
raise ctypes.WinError(ctypes.get_last_error())
return volumes

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com