-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crash when working with node-ffi on Windows and Mac #2791
Comments
I think we're having this very same error on MAC too there: node-ffi/node-ffi#239 This is the most simplest repro case that we have. Interesting that this only happens on MAC, instead of the above Windows only case. |
@unbornchikken all buffer memory should be aligned now, except the slices that are created by user code. In other words: var a = new Buffer(8); // aligned
var b = a.slice(1); // not-aligned, pointing to the interior of `a` Do you have any test case to reproduce the problem? |
I mean for mac? |
Please find the intro comment there: node-ffi/node-ffi#239 Very easy to reproduce. |
Confirmed:
|
On Windows with that iTunes DLL I have the very same stack trace, that's why I think those are related. This gotta be some pointer layout issue again, ain't this? |
Sorry, but I won't be able to finish it today (it is already 4:28 am), will continue looking tomorrow! |
I know what's happening, it tries to treat the internal data as a pointer to the heap value. Namely, |
Yup, makes sense. That was my first guess for #2484 too. |
Thanks guys, I'm ready to help with testing of the fix :) |
Candidate fix is: diff --git a/deps/v8/src/heap/objects-visiting-inl.h b/deps/v8/src/heap/objects-visiting-inl.h
index 0103054..09b1d48 100644
--- a/deps/v8/src/heap/objects-visiting-inl.h
+++ b/deps/v8/src/heap/objects-visiting-inl.h
@@ -81,10 +81,8 @@ int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer(
Map* map, HeapObject* object) {
Heap* heap = map->GetHeap();
- VisitPointers(
- heap,
- HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
- HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
+ JSArrayBuffer::BodyDescriptor::IterateBody<
+ StaticNewSpaceVisitor<StaticVisitor> >(heap, object);
if (!JSArrayBuffer::cast(object)->is_external()) {
heap->RegisterLiveArrayBuffer(true,
JSArrayBuffer::cast(object)->backing_store());
@@ -503,10 +501,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
Map* map, HeapObject* object) {
Heap* heap = map->GetHeap();
- StaticVisitor::VisitPointers(
- heap,
- HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
- HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
+ JSArrayBuffer::BodyDescriptor::IterateBody<StaticVisitor>(heap, object);
if (!JSArrayBuffer::cast(object)->is_external()) {
heap->RegisterLiveArrayBuffer(false,
JSArrayBuffer::cast(object)->backing_store());
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index fbc2c4e..1e2fe15 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -6091,6 +6091,34 @@ void JSArrayBuffer::set_is_shared(bool value) {
}
+// static
+template<typename StaticVisitor>
+void JSArrayBuffer::BodyDescriptor::IterateBody(Heap* heap, HeapObject* obj) {
+ StaticVisitor::VisitPointers(
+ heap,
+ HeapObject::RawField(obj, JSArrayBuffer::BodyDescriptor::kStartOffset),
+ HeapObject::RawField(obj, JSArrayBuffer::kBackingStoreOffset));
+ StaticVisitor::VisitPointers(
+ heap,
+ HeapObject::RawField(obj,
+ JSArrayBuffer::kBackingStoreOffset + kPointerSize),
+ HeapObject::RawField(obj, JSArrayBuffer::kSizeWithInternalFields));
+}
+
+
+void JSArrayBuffer::BodyDescriptor::IterateBody(HeapObject* obj,
+ ObjectVisitor* v) {
+ v->VisitPointers(
+ HeapObject::RawField(obj, JSArrayBuffer::BodyDescriptor::kStartOffset),
+ HeapObject::RawField(obj, JSArrayBuffer::kBackingStoreOffset));
+ v->VisitPointers(
+ HeapObject::RawField(obj,
+ JSArrayBuffer::kBackingStoreOffset + kPointerSize),
+ HeapObject::RawField(obj, JSArrayBuffer::kSizeWithInternalFields));
+}
+
+
+
Object* JSArrayBufferView::byte_offset() const {
if (WasNeutered()) return Smi::FromInt(0);
return Object::cast(READ_FIELD(this, kByteOffsetOffset));
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 2b042fd..efc168c 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -1420,7 +1420,6 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case JS_VALUE_TYPE:
case JS_DATE_TYPE:
case JS_ARRAY_TYPE:
- case JS_ARRAY_BUFFER_TYPE:
case JS_TYPED_ARRAY_TYPE:
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
@@ -1436,6 +1435,9 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case JS_MESSAGE_OBJECT_TYPE:
JSObject::BodyDescriptor::IterateBody(this, object_size, v);
break;
+ case JS_ARRAY_BUFFER_TYPE:
+ JSArrayBuffer::BodyDescriptor::IterateBody(this, v);
+ break;
case JS_FUNCTION_TYPE:
reinterpret_cast<JSFunction*>(this)
->JSFunctionIterateBody(object_size, v);
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 7e4fcba..8b62720 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -10027,6 +10027,18 @@ class JSArrayBuffer: public JSObject {
static const int kSizeWithInternalFields =
kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize;
+ class BodyDescriptor {
+ public:
+ static const int kStartOffset = JSObject::BodyDescriptor::kStartOffset;
+ static const int kEndOffset = kSizeWithInternalFields - kPointerSize;
+ static const int kSize = kSizeWithInternalFields;
+
+ template<typename StaticVisitor>
+ static inline void IterateBody(Heap* heap, HeapObject* obj);
+
+ static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
+ };
+
class IsExternal : public BitField<bool, 1, 1> {};
class IsNeuterable : public BitField<bool, 2, 1> {};
class WasNeutered : public BitField<bool, 3, 1> {}; Working on a test for v8. |
Unfortunately, we can't land it as it is, because I'm not sure if the supplied fix covers all edge cases in v8. Let's wait until it will land in upstream, and backport it to our v8. |
Cannot we invent a workaround? I'm thinking about that we have a GC callback at Buffer side, so we can hook in some behavior before GC happens. So cannot that poiner be nullified there before v8 could even touch it? |
And in |
@unbornchikken this is should land in v8 upstream pretty soon. All of my previous CLs were reviewed and landed in days, depending on how many changes were required before the green light. Workaround might be to allocate buffers aligned and slice them up to get the proper address... I think it should work? |
But again, I wouldn't go too far with this. Perhaps 4.0.1 with this fix will be released fast enough. |
In upstream we trust then. Thanks. |
ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: nodejs/node#2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{#30771}
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: nodejs#2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{nodejs#30771} Fix: nodejs#2791
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: #2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{#30771} Fix: #2791 PR-URL: #2912 Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Fixed by 2b8a06b. Thanks for report! |
Maybe they talks to each other in person, just like other(than us) human beings. :) |
Thank you very much guys, I'll test the fix very soon and I'll inform you for the results. |
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: #2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{#30771} Fix: #2791 PR-URL: #2912 Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: nodejs#2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{nodejs#30771} Fix: nodejs#2791 PR-URL: nodejs#2912 Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
@indutny can we backport this to io.js v3 (assuming we're still doing patch releases for it)? |
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: nodejs#2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{nodejs#30771} Fix: nodejs#2791 PR-URL: nodejs#2912 Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: #2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{#30771} Fix: #2791 PR-URL: #2912 Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: #2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{#30771} Fix: #2791 PR-URL: #2912 Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: nodejs#2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{nodejs#30771} Ref: nodejs#2791 Ref: nodejs#2912 PR-URL: nodejs#3351 Reviewed-By: indutny - Fedor Indutny <[email protected]> Reviewed-By: bnoordhuis - Ben Noordhuis <[email protected]>
Original commit message: [objects] do not visit ArrayBuffer's backing store ArrayBuffer's backing store is a pointer to external heap, and can't be treated as a heap object. Doing so will result in crashes, when the backing store is unaligned. See: #2791 BUG=chromium:530531 [email protected] LOG=N Review URL: https://codereview.chromium.org/1327403002 Cr-Commit-Position: refs/heads/master@{#30771} Ref: #2791 Ref: #2912 PR-URL: #3351 Reviewed-By: indutny - Fedor Indutny <[email protected]> Reviewed-By: bnoordhuis - Ben Noordhuis <[email protected]>
I don't mind, but can't say that I am ready to invest time into it. If someone will open a PR - I will review it. |
Hi,
One of the popular npm modules is node-ffi. We are using it in our code for several different calls, but one of them leads to assertion error in node 3.x or later. As the same code of the node-ffi is working fine with iojs 2.x, node 0.12.x and node 0.10.x and after discussion with node-ffi owners, I came to opening this issue.
In our code we are trying to call methods from CoreFoundation.dll, which is part of iTunes installation. When we have some short calls and our process terminates, everything is working fine. But when our process starts working for some long time, we receive Assertion error:
It looks like the garbage collector had collected something that we are trying to use later.
So we've tried to simplify the reproduction case and we've found that we fail only when trying to create ForeignFunction for specific method of the dll. Please note - we are not using them in the test script, just using ffi.
You can find the repro script and the output when DEBUG=* in this gist
Please note that the crash is on global.gc() call.
I believe the problem is not in the dll itself, as the same code is working fine with node 0.10, node 0.12, iojs 2.x
We suspect that this change had not fixed all issues related to buffers and garbage collection.
The original issue in node-ffi is here. After some time of debugging, @unbornchikken stated:
Could you please advise what's going wrong here? I know that it is related to specific npm module, not to the node itself, but the same module is working fine in all other cases and node versions, only the call to this specific method is failing on iojs 3.x and node 4.0.0.
Thanks in advance for your help!
The text was updated successfully, but these errors were encountered: