Properly discarding ctypes pointers to mmap memory in Python





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I have the issue that I cannot properly close mmap-s in Python after I created a pointer to them. My use case is that I open files (usually that is UIO-devices to work with hardware, but the issue also happens with normal files), memory-map them and then use them as buffers for ctypes-structures. Usually structs or arrays of data. A minimal example looks like this:



import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here

del memory
map.close()
os.close(fileno)


Everything is fine at that point.



However, sometimes I need to call some C library functions that also need access to that memory so I have to pass in a pointer to them. I create that pointer using:



ptr = ct.cast(memory, ct.c_void_p)


All of that works very well except one thing. As soon as I create such a pointer, I can no longer close the memory map. Take this slightly extended example:



import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here
ptr = ct.cast(memory, ct.c_void_p)
del ptr

del memory
map.close()
os.close(fileno)


Running this results in the following exception:



Traceback (most recent call last):
File "pointer_test.py", line 14, in <module>
map.close()
BufferError: cannot close exported pointers exist

Process finished with exit code 1


I've run some analysis (using gc.get_referrers) on what is referencing the map-instance and it turns out that there is a memoryview-instance still there. In the end, this traces back to the ctypes Array:



[<__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
[{547965620704: <__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
'ffffffff': <memory at 0x7f95621a08>},
[<memory at 0x7f95621a08>,
[<managedbuffer object at 0x7f95746d08>,


However, this does not really help me. I'd like to know how I can get rid of that pointer. I know that this is likely not fully safe since I could, of course, always have a copy of that pointer somewhere. But completely preventing closing the mmap after a pointer was created also does not seem like a good idea. Anyone knows how I can convince Python that I discarded all the pointers and it is now safe to close the mmap?










share|improve this question























  • Did the same test as you and got the same result. I thought it was just a ref being kept by python somewhere, so I just did: import gc and gc.collect() and tried to close the mem mapped file immediately after that: it worked... I can't see any other way to tell python that there are no refs on the mem map :(

    – Neitsa
    Nov 20 '18 at 9:05




















1















I have the issue that I cannot properly close mmap-s in Python after I created a pointer to them. My use case is that I open files (usually that is UIO-devices to work with hardware, but the issue also happens with normal files), memory-map them and then use them as buffers for ctypes-structures. Usually structs or arrays of data. A minimal example looks like this:



import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here

del memory
map.close()
os.close(fileno)


Everything is fine at that point.



However, sometimes I need to call some C library functions that also need access to that memory so I have to pass in a pointer to them. I create that pointer using:



ptr = ct.cast(memory, ct.c_void_p)


All of that works very well except one thing. As soon as I create such a pointer, I can no longer close the memory map. Take this slightly extended example:



import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here
ptr = ct.cast(memory, ct.c_void_p)
del ptr

del memory
map.close()
os.close(fileno)


Running this results in the following exception:



Traceback (most recent call last):
File "pointer_test.py", line 14, in <module>
map.close()
BufferError: cannot close exported pointers exist

Process finished with exit code 1


I've run some analysis (using gc.get_referrers) on what is referencing the map-instance and it turns out that there is a memoryview-instance still there. In the end, this traces back to the ctypes Array:



[<__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
[{547965620704: <__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
'ffffffff': <memory at 0x7f95621a08>},
[<memory at 0x7f95621a08>,
[<managedbuffer object at 0x7f95746d08>,


However, this does not really help me. I'd like to know how I can get rid of that pointer. I know that this is likely not fully safe since I could, of course, always have a copy of that pointer somewhere. But completely preventing closing the mmap after a pointer was created also does not seem like a good idea. Anyone knows how I can convince Python that I discarded all the pointers and it is now safe to close the mmap?










share|improve this question























  • Did the same test as you and got the same result. I thought it was just a ref being kept by python somewhere, so I just did: import gc and gc.collect() and tried to close the mem mapped file immediately after that: it worked... I can't see any other way to tell python that there are no refs on the mem map :(

    – Neitsa
    Nov 20 '18 at 9:05
















1












1








1








I have the issue that I cannot properly close mmap-s in Python after I created a pointer to them. My use case is that I open files (usually that is UIO-devices to work with hardware, but the issue also happens with normal files), memory-map them and then use them as buffers for ctypes-structures. Usually structs or arrays of data. A minimal example looks like this:



import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here

del memory
map.close()
os.close(fileno)


Everything is fine at that point.



However, sometimes I need to call some C library functions that also need access to that memory so I have to pass in a pointer to them. I create that pointer using:



ptr = ct.cast(memory, ct.c_void_p)


All of that works very well except one thing. As soon as I create such a pointer, I can no longer close the memory map. Take this slightly extended example:



import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here
ptr = ct.cast(memory, ct.c_void_p)
del ptr

del memory
map.close()
os.close(fileno)


Running this results in the following exception:



Traceback (most recent call last):
File "pointer_test.py", line 14, in <module>
map.close()
BufferError: cannot close exported pointers exist

Process finished with exit code 1


I've run some analysis (using gc.get_referrers) on what is referencing the map-instance and it turns out that there is a memoryview-instance still there. In the end, this traces back to the ctypes Array:



[<__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
[{547965620704: <__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
'ffffffff': <memory at 0x7f95621a08>},
[<memory at 0x7f95621a08>,
[<managedbuffer object at 0x7f95746d08>,


However, this does not really help me. I'd like to know how I can get rid of that pointer. I know that this is likely not fully safe since I could, of course, always have a copy of that pointer somewhere. But completely preventing closing the mmap after a pointer was created also does not seem like a good idea. Anyone knows how I can convince Python that I discarded all the pointers and it is now safe to close the mmap?










share|improve this question














I have the issue that I cannot properly close mmap-s in Python after I created a pointer to them. My use case is that I open files (usually that is UIO-devices to work with hardware, but the issue also happens with normal files), memory-map them and then use them as buffers for ctypes-structures. Usually structs or arrays of data. A minimal example looks like this:



import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here

del memory
map.close()
os.close(fileno)


Everything is fine at that point.



However, sometimes I need to call some C library functions that also need access to that memory so I have to pass in a pointer to them. I create that pointer using:



ptr = ct.cast(memory, ct.c_void_p)


All of that works very well except one thing. As soon as I create such a pointer, I can no longer close the memory map. Take this slightly extended example:



import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here
ptr = ct.cast(memory, ct.c_void_p)
del ptr

del memory
map.close()
os.close(fileno)


Running this results in the following exception:



Traceback (most recent call last):
File "pointer_test.py", line 14, in <module>
map.close()
BufferError: cannot close exported pointers exist

Process finished with exit code 1


I've run some analysis (using gc.get_referrers) on what is referencing the map-instance and it turns out that there is a memoryview-instance still there. In the end, this traces back to the ctypes Array:



[<__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
[{547965620704: <__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
'ffffffff': <memory at 0x7f95621a08>},
[<memory at 0x7f95621a08>,
[<managedbuffer object at 0x7f95746d08>,


However, this does not really help me. I'd like to know how I can get rid of that pointer. I know that this is likely not fully safe since I could, of course, always have a copy of that pointer somewhere. But completely preventing closing the mmap after a pointer was created also does not seem like a good idea. Anyone knows how I can convince Python that I discarded all the pointers and it is now safe to close the mmap?







python pointers ctypes mmap memoryview






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 16 '18 at 14:38









janjan

407415




407415













  • Did the same test as you and got the same result. I thought it was just a ref being kept by python somewhere, so I just did: import gc and gc.collect() and tried to close the mem mapped file immediately after that: it worked... I can't see any other way to tell python that there are no refs on the mem map :(

    – Neitsa
    Nov 20 '18 at 9:05





















  • Did the same test as you and got the same result. I thought it was just a ref being kept by python somewhere, so I just did: import gc and gc.collect() and tried to close the mem mapped file immediately after that: it worked... I can't see any other way to tell python that there are no refs on the mem map :(

    – Neitsa
    Nov 20 '18 at 9:05



















Did the same test as you and got the same result. I thought it was just a ref being kept by python somewhere, so I just did: import gc and gc.collect() and tried to close the mem mapped file immediately after that: it worked... I can't see any other way to tell python that there are no refs on the mem map :(

– Neitsa
Nov 20 '18 at 9:05







Did the same test as you and got the same result. I thought it was just a ref being kept by python somewhere, so I just did: import gc and gc.collect() and tried to close the mem mapped file immediately after that: it worked... I can't see any other way to tell python that there are no refs on the mem map :(

– Neitsa
Nov 20 '18 at 9:05














0






active

oldest

votes












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53339931%2fproperly-discarding-ctypes-pointers-to-mmap-memory-in-python%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53339931%2fproperly-discarding-ctypes-pointers-to-mmap-memory-in-python%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Xamarin.iOS Cant Deploy on Iphone

Glorious Revolution

Dulmage-Mendelsohn matrix decomposition in Python