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;
}
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
add a comment |
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
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
andgc.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
add a comment |
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
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
python pointers ctypes mmap memoryview
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
andgc.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
add a comment |
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
andgc.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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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
andgc.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