Why is a `node-ffi` Callback returning an empty Buffer with `void *` but not with `int *`? - node.js

I'm working on implementing a callback using node-ffi with the following signature:
const callback = ffi.Callback('void', ['int', 'void *'], (eMsg, pData) => {
console.log(pData);
console.log(`Buffer deref: ${ref.get(pData)}`);
});
The underlying C library calls this with a void * value for pData. About half of the callbacks actually return an int * value and, in the other half, pData is more complex data (i.e. Struct). The ref.get(pData) ends up being null. If I change the Callback definition to use int * instead of void *, ref.get(pData) returns the correct value. What I can't figure out is why the void * ends up being a Buffer with a size of 0 that does not dereference properly (even when pData is an int *).
I feel like I'm missing something but can't, for the life of me, see what that would be. Can anyone help?

I had a similar problem, and what I did was set the length property of the returned Buffer to the size of the thing that will be returned.
Because it is void * type, node-ffi basically does not know how long of Buffer will be returned to it.
so in this case, pData.length = <size of structure> should fix it.

Related

Is it possible using variables of ArgumentMatchers?

Let's say I have an interface looks like this.
interface Some {
/**
* Does some on specified array with specified index and returns the array.
*
* #param array the array.
* #param index the index.
* #returns given {#code array}.
*/
byte[] some(byte[] array, int index);
}
Here comes a simple stubbing make the some method just return given array.
Some some = spy(Some.class);
when(some.some(any(), anyInt())
.thenAnswer(i -> i.getArguments(0)};
Is it possible or does it make any sense modifying above code like this?
Some some = spy(Some.class);
byte[] array = any(); // ##?
int index = anyInt(); // ##?
when(some.some(array, index) // ##?
.thenAnswer(i -> i.getArguments(0)};
Does it have same or equivalent effects?
In the code posted, the test passes and the effect is equivalent. This is not true in the general case, and you can easily break the code.
For example this works:
Some some = mock(Some.class);
byte[] any = any();
int index = anyInt();
when(some.some(any, index)).thenAnswer(i -> i.getArguments()[0]);
var res = some.some(new byte[]{1, 2}, 4);
While this with reordered variables does not work:
Some some = mock(Some.class);
int index = anyInt();
byte[] any = any();
when(some.some(any, index)).thenAnswer(i -> i.getArguments()[0]);
var res = some.some(new byte[]{1, 2}, 4);
Please refer to How do Mockito matchers work?:
Implementation details
Matchers are stored (as Hamcrest-style object matchers) in a stack contained in a class called ArgumentMatcherStorage. MockitoCore and Matchers each own a ThreadSafeMockingProgress instance, which statically contains a ThreadLocal holding MockingProgress instances. It's this MockingProgressImpl that holds a concrete ArgumentMatcherStorageImpl. Consequently, mock and matcher state is static but thread-scoped consistently between the Mockito and Matchers classes.
Most matcher calls only add to this stack, with an exception for matchers like and, or, and not. This perfectly corresponds to (and relies on) the evaluation order of Java, which evaluates arguments left-to-right before invoking a method:
when(foo.quux(anyInt(), and(gt(10), lt(20)))).thenReturn(true);
[6] [5] [1] [4] [2] [3]
This will:
Add anyInt() to the stack.
Add gt(10) to the stack.
Add lt(20) to the stack.
Remove gt(10) and lt(20) and add and(gt(10), lt(20)).
Call foo.quux(0, 0), which (unless otherwise stubbed) returns the default value false. Internally Mockito marks quux(int, int) as the most recent call.
Call when(false), which discards its argument and prepares to stub method quux(int, int) identified in 5. The only two valid states are with stack length 0 (equality) or 2 (matchers), and there are two matchers on the stack (steps 1 and 4), so Mockito stubs the method with an any() matcher for its first argument and and(gt(10), lt(20)) for its second argument and clears the stack.
This demonstrates a few rules:
Mockito can't tell the difference between quux(anyInt(), 0) and quux(0, anyInt()). They both look like a call to quux(0, 0) with one int matcher on the stack. Consequently, if you use one matcher, you have to match all arguments.
Call order isn't just important, it's what makes this all work. Extracting matchers to variables generally doesn't work, because it usually changes the call order. Extracting matchers to methods, however, works great.
int between10And20 = and(gt(10), lt(20));
/* BAD */ when(foo.quux(anyInt(), between10And20)).thenReturn(true);
// Mockito sees the stack as the opposite: and(gt(10), lt(20)), anyInt().
public static int anyIntBetween10And20() { return and(gt(10), lt(20)); }
/* OK */ when(foo.quux(anyInt(), anyIntBetween10And20())).thenReturn(true);
// The helper method calls the matcher methods in the right order.

COleDateTime::SetDateTime and noexcept (code analysis)

See this code:
COleDateTime CSpecialEventDlg::GetSpecialEventDate() noexcept
{
COleDateTime datEvent;
if (datEvent.SetDateTime(m_datEvent.GetYear(),
m_datEvent.GetMonth(),
m_datEvent.GetDay(),
0, 0, 0) != 0)
{
// Error
}
return datEvent;
}
My code analysis said I could add noexcept (which I did). But I decided to investigate a little more. I noticed that SetDateTime returns a value:
Zero if the value of this COleDateTime object was set successfully; otherwise, 1. This return value is based on the DateTimeStatus enumerated type. For more information, see the SetStatus member function.
For that latter function (SetStatus) it states:
The status parameter value is defined by the DateTimeStatus enumerated type, which is defined within the COleDateTime class. See COleDateTime::GetStatus for details.
Now, the documentation for GetStatus is documented to have a definition of:
DateTimeStatus GetStatus() const throw();
So, it throws an exception if there is an error. Therefore, I decided to look at the MFC source for SetDateTime:
inline int COleDateTime::SetDateTime(
_In_ int nYear,
_In_ int nMonth,
_In_ int nDay,
_In_ int nHour,
_In_ int nMin,
_In_ int nSec) throw()
{
SYSTEMTIME st;
::ZeroMemory(&st, sizeof(SYSTEMTIME));
st.wYear = WORD(nYear);
st.wMonth = WORD(nMonth);
st.wDay = WORD(nDay);
st.wHour = WORD(nHour);
st.wMinute = WORD(nMin);
st.wSecond = WORD(nSec);
m_status = ConvertSystemTimeToVariantTime(st) ? valid : invalid;
return m_status;
}
It uses ConvertSystemTimeToVariantTime to set the status. That uses:
inline BOOL COleDateTime::ConvertSystemTimeToVariantTime(_In_ const SYSTEMTIME& systimeSrc)
{
return AtlConvertSystemTimeToVariantTime(systimeSrc,&m_dt);
}
And that uses:
inline BOOL AtlConvertSystemTimeToVariantTime(
_In_ const SYSTEMTIME& systimeSrc,
_Out_ double* pVarDtTm)
{
ATLENSURE(pVarDtTm!=NULL);
//Convert using ::SystemTimeToVariantTime and store the result in pVarDtTm then
//convert variant time back to system time and compare to original system time.
BOOL ok = ::SystemTimeToVariantTime(const_cast<SYSTEMTIME*>(&systimeSrc), pVarDtTm);
SYSTEMTIME sysTime;
::ZeroMemory(&sysTime, sizeof(SYSTEMTIME));
ok = ok && ::VariantTimeToSystemTime(*pVarDtTm, &sysTime);
ok = ok && (systimeSrc.wYear == sysTime.wYear &&
systimeSrc.wMonth == sysTime.wMonth &&
systimeSrc.wDay == sysTime.wDay &&
systimeSrc.wHour == sysTime.wHour &&
systimeSrc.wMinute == sysTime.wMinute &&
systimeSrc.wSecond == sysTime.wSecond);
return ok;
}
At this point I have got lost. In short, I am assuming that SetDateTime does not throw an exception.
I understand this much, if I decide to make a call to GetStatus inside the if clause then we do have a potential for exception to be thrown.
All three MFC functions for which you have shown the source code (COleDateTime::SetDateTime, COleDateTime::ConvertSystemTimeToVariantTime and AtlConvertSystemTimeToVariantTime) have – according to their declarations – the potential to throw exceptions (because they have no specification to the contrary, such as noexcept).
However, that doesn't mean that they will (or are even likely to). Digging a bit further into the MFC source code, the only place I can see, in those three functions, where an exception could be thrown is in the ATLENSURE(pVarDtTm!=NULL); line (in the third function).
The ATLENSURE macro is defined as follows:
#define ATLENSURE(expr) ATLENSURE_THROW(expr, E_FAIL)
And ATLENSURE_THROW is, in turn, defined thus:
#define ATLENSURE_THROW(expr, hr) \
do { \
int __atl_condVal=!!(expr); \
ATLASSUME(__atl_condVal); \
if(!(__atl_condVal)) AtlThrow(hr); \
} __pragma(warning(suppress:4127)) while (0)
So, it would seem that, in your code, an exception will be thrown if expr (in the above snippets) is null (the double-bang, !! pseudo-operator makes any non-zero value into 1 and leaves a zero as zero). That expr is the result of the pVarDtTm!=NULL expression, which can only be 0 (false) if the &m_dt argument in the call in your second MFC source excerpt is itself NULL – and, as the address of a member of the class object through which it is being called, that seems improbable (if not impossible).
Another issue you have is that you appear to misunderstand what the throw() specification in the DateTimeStatus GetStatus() const throw(); declaration means. As described here, it is actually (since C++17) an alias for noexcept (or noexcept(true), to be more precise). To specify that a function can throw any type of exception, the throw(...) or noexcept(false) specifications should be used (or use no except/throw specification at all).
So, your last sentence is not really true:
I understand this much, if I decide to make a call to GetStatus inside the if clause then we do have a potential for exception to be
thrown.
Because the GetStatus() function is specified explicitly as non-throwing, and you already have a call to the SetDateTime member function, which (as described above) can throw an exception (but won't, in your code).

ff_replay substructure in ff_effect empty

I am developing a force feedback driver (linux) for a yet unsupported gamepad.
Whenever a application in userspace requests a ff-effect (e.g rumbling), a function in my driver is called:
static int foo_ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
this is set by the following code inside my init function:
input_set_capability(dev, EV_FF, FF_RUMBLE);
input_ff_create_memless(dev, NULL, foo_ff_play);
I'm accessing the ff_effect struct (which is passed to my foo_ff_play function) like this:
static int foo_ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
{
u16 length;
length = effect->replay.length;
printk(KERN_DEBUG "length: %i", length);
return 0;
}
The problem is, that the reported length (in ff_effect->replay) is always zero.
That's confusing, since i am running fftest on my device, and fftest definitely sets the length attribute: https://github.com/flosse/linuxconsole/blob/master/utils/fftest.c (line 308)
/* a strong rumbling effect */
effects[4].type = FF_RUMBLE;
effects[4].id = -1;
effects[4].u.rumble.strong_magnitude = 0x8000;
effects[4].u.rumble.weak_magnitude = 0;
effects[4].replay.length = 5000;
effects[4].replay.delay = 1000;
Does this have something to do with the "memlessness"? Why does the data in ff_replay seem to be zero if it isn't?
Thank you in advance
Why is the replay struct empty?
Taking a look at https://elixir.free-electrons.com/linux/v4.4/source/drivers/input/ff-memless.c#L406 we find:
static void ml_play_effects(struct ml_device *ml)
{
struct ff_effect effect;
DECLARE_BITMAP(handled_bm, FF_MEMLESS_EFFECTS);
memset(handled_bm, 0, sizeof(handled_bm));
while (ml_get_combo_effect(ml, handled_bm, &effect))
ml->play_effect(ml->dev, ml->private, &effect);
ml_schedule_timer(ml);
}
ml_get_combo_effect sets the effect by calling ml_combine_effects., but ml_combine_effects simply does not copy replay.length to the ff_effect struct which is passed to our foo_play_effect (at least not if the effect-type is FF_RUMBLE): https://elixir.free-electrons.com/linux/v4.4/source/drivers/input/ff-memless.c#L286
That's why we cannot read out the ff_replay-data in our foo_play_effect function.
Okay, replay is empty - how can we determine how long we have to play the effect (e.g. FF_RUMBLE) then?
Looks like the replay structure is something we do not even need to carry about. Yes, fftest sets the length and then uploads the effect to the driver, but if we take a look at ml_ff_upload (https://elixir.free-electrons.com/linux/v4.4/source/drivers/input/ff-memless.c#L481), we can see the following:
if (test_bit(FF_EFFECT_STARTED, &state->flags)) {
__clear_bit(FF_EFFECT_PLAYING, &state->flags);
state->play_at = jiffies +
msecs_to_jiffies(state->effect->replay.delay);
state->stop_at = state->play_at +
msecs_to_jiffies(state->effect->replay.length);
state->adj_at = state->play_at;
ml_schedule_timer(ml);
}
That means that the duration is already handled by the input-subsystem. It starts the effect and also stops it as needed.
Furthermore we can see at https://elixir.free-electrons.com/linux/v4.4/source/include/uapi/linux/input.h#L279 that
/*
* All duration values are expressed in ms. Values above 32767 ms (0x7fff)
* should not be used and have unspecified results.
*/
That means that we have to make our effect play at least 32767ms. Everything else (stopping the effect before) is up to the scheduler - which is not our part :D

JNA - Use structure array as byref argument

I know parts of this issue is covered by some posts here and I have looked at them and tested some but with no luck.
I have this native method signature which should populate the provided CBadgeData structure array with results:
int elc_GetBadges(int nHandle, char* cErr, int* nRecCount, CBadgeData** arr)
The CBadgeData structure is implemented as follows:
package test.elcprog;
import java.util.Arrays;
import java.util.List;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
public class CBadgeData extends Structure{
public static class ByReference extends CBadgeData implements Structure.ByReference { }
public int nBadgeID, nTrigger, nExtraData;
public String cName;
public CBadgeData(Pointer pointer){
super(pointer);
}
public CBadgeData(){ }
public String ToString() {
return nBadgeID + "," + nTrigger + "," + nExtraData + "," + cName;
}
#Override
protected List getFieldOrder() {
String[] s = new String[]{"nBadgeID","nTrigger","nExtraData","cName"};
return Arrays.asList(s);
}
}
My last try to craft this argument and call the method looked like this:
CBadgeData.ByReference[] badges = new CBadgeData.ByReference[max_items];
new CBadgeData.ByReference().toArray(badges);
int ret = inst.elc_GetBadges(handle, err, recCount, badges);
It fails with segmentation error.
My Question is what Java type should be provided here as an argument for the native CBadgeData** in the call to elc_GetBadges?
EDIT -1-
Populating the array myself (with or without terminating null pointer) didn't work and caused further Seg crashes. I then used Pointer[] arg as technomage suggested:
Pointer[] pointers = new Pointer[max_items];
for(int i=0; i<max_items; i++){
pointers[i] = new CBadgeData.ByReference().getPointer();
}
int ret = inst.elc_GetBadges(handle, err, recCount, pointers);
This caused no error but seems to not make any changes to the returning struct which should have contain 4 items in this case:
int bid = new CBadgeData(pointers[i]).nBadgeID; // this returns null for all items
Using explicit read() / write() on the struct led to Seg crashes again (on the read):
Any idea what am I still missing here?
EDIT -2-
Interestingly enough - using the Memory.get directly, after calling the native method, gets the correct results:
Memory m= (Memory)pointers[0];
System.out.println("1st int: "+m.getInt(0)); // this gets 24289 which is 5ee1
System.out.println("2nd int: "+m.getInt(4)); // this gets 3
System.out.println("3rd int: "+m.getInt(8)); // this gets 255
System.out.println("String: "+m.getString(12)); // this gets "Badge[5EE1]" as supposed
But the read() still crashes. Any thoughts?
I'm inferring that CBadgeData** input is intended to be an array of pointer to CBadgeData.
As such, the Structure.ByReference tagging is correct.
Structure.toArray() is probably not appropriate here, or at least not necessary (it allocates a contiguous block of structs in memory). You can just populate your array with CBadgeData.ByReference instances.
Perhaps your callee is expecting a NULL pointer at the end of the array? I don't see another indicator of the array length to the callee.
CBadgeData.ByReference[] badges = new CBadgeData.ByReference[max_items+1];
for (int i=0;i < badges.length-1;i++) {
badges[i] = new CBadgeData.ByReference();
}
badges[badges.length-1] = null;
Pretty sure that works. If for whatever reason there's a bug handling Structure.ByReference[], I know that Pointer[] is reliable and will do the same thing.
EDIT
If you use Pointer[] instead of Structure.ByReference[] (please post a bug to the project site if Structure.ByReference[] does not work), you will have to manually call Structure.write/read before/after your native function call, since JNA will not know that the pointers reference structures that need to be synched with native memory. I'd bet, however, that the cause of your crashes when using Structure.ByReference[] was simply that JNA was automatically calling Structure.read() after the call and triggered the same error that you see when calling it explicitly.
If you get a segfault on read, it likely means that your structure fields aren't properly aligned or defined, or (less likely) that you have corrupt data that can't be read properly. To diagnose this, set jna.dump_memory=true and print out your struct after calling Structure.write() to see if the contents of the structure appear as you'd expect. It'd also help to post the native and JNA forms of your structure here, if possible.

MFC multithreading with delete[] , dbgheap.c

I've got a strange problem and really don't understand what's going on.
I made my application multi-threaded using the MFC multithreadclasses.
Everything works well so far, but now:
Somewhere in the beginning of the code I create the threads:
m_bucketCreator = new BucketCreator(128,128,32);
CEvent* updateEvent = new CEvent(FALSE, FALSE);
CWinThread** threads = new CWinThread*[numThreads];
for(int i=0; i<8; i++){
threads[i]=AfxBeginThread(&MyClass::threadfunction, updateEvent);
m_activeRenderThreads++;
}
this creates 8 threads working on this function:
UINT MyClass::threadfunction( LPVOID params ) //executed in new Thread
{
Bucket* bucket=m_bucketCreator.getNextBucket();
...do something with bucket...
delete bucket;
}
m_bucketCreator is a static member. Now I get some thread error in the deconstructor of Bucket on the attempt to delete a buffer (however, the way I understand it this buffer should be in the memory of this thread, so I don't get why there is an error). On the attempt of delete[] buffer, the error happens in _CrtIsValidHeapPointer() in dbgheap.c.
Visual studio outputs the message that it trapped a halting point and this can be either due to heap corruption or because the user pressed f12 (I didn't ;) )
class BucketCreator {
public:
BucketCreator();
~BucketCreator(void);
void init(int resX, int resY, int bucketSize);
Bucket* getNextBucket(){
Bucket* bucket=NULL;
//enter critical section
CSingleLock singleLock(&m_criticalSection);
singleLock.Lock();
int height = min(m_resolutionY-m_nextY,m_bucketSize);
int width = min(m_resolutionX-m_nextX,m_bucketSize);
bucket = new Bucket(width, height);
//leave critical section
singleLock.Unlock();
return bucket;
}
private:
int m_resolutionX;
int m_resolutionY;
int m_bucketSize;
int m_nextX;
int m_nextY;
//multithreading:
CCriticalSection m_criticalSection;
};
and class Bucket:
class Bucket : public CObject{
DECLARE_DYNAMIC(RenderBucket)
public:
Bucket(int a_resX, int a_resY){
resX = a_resX;
resY = a_resY;
buffer = new float[3 * resX * resY];
int buffersize = 3*resX * resY;
for (int i=0; i<buffersize; i++){
buffer[i] = 0;
}
}
~Bucket(void){
delete[] buffer;
buffer=NULL;
}
int getResX(){return resX;}
int getResY(){return resY;}
float* getBuffer(){return buffer;}
private:
int resX;
int resY;
float* buffer;
Bucket& operator = (const Bucket& other) { /*..*/}
Bucket(const Bucket& other) {/*..*/}
};
Can anyone tell me what could be the problem here?
edit: this is the other static function I'm calling from the threads. Is this safe to do?
static std::vector<Vector3> generate_poisson(double width, double height, double min_dist, int k, std::vector<std::vector<Vector3> > existingPoints)
{
CSingleLock singleLock(&m_criticalSection);
singleLock.Lock();
std::vector<Vector3> samplePoints = std::vector<Vector3>();
...fill the vector...
singleLock.Unlock();
return samplePoints;
}
All the previous replies are sound. For the copy constructor, make sure that it doesn't just copy the buffer pointer, otherwise that will cause the problem. It needs to allocate a new buffer, not the pointer value, which would cause an error in 'delete'. But I don't get the impression that the copy contructor will get called in your code.
I've looked at the code and I am not seeing any error in it as is. Note that the thread synchronization isn't even necessary in this GetNextBucket code, since it's returning a local variable and those are pre-thread.
Errors in ValidateHeapPointer occur because something has corrupted the heap, which happens when a pointer writes past a block of memory. Often it's a for() loop that goes too far, a buffer that wasn't allocated large enough, etc.
The error is reported during a call to 'delete' because that's when the heap is validated for bugs in debug mode. However, the error has occurred before that time, it just happens that the heap is checked only in 'new' and 'delete'. Also, it isn't necessarily related to the 'Bucket' class.
What you need to need to find this bug, short of using tools like BoundsChecker or HeapValidator, is comment out sections of your code until it goes away, and then you'll find the offending code.
There is another method to narrow down the problem. In debug mode, include in your code, and sprinkle calls to _CrtCheckMemory() at various points of interest. That will generate the error when the heap is corrupted. Simply move the calls in your code to narrow down at what point the corruption begins to occur.
I don't know which version of Visual C++ you are using. If you're using a earlier one like VC++ 6.0, make sure that you are using the Multitreaded DLL version of the C Run Time Library in the compiler option.
You're constructing a RenderBucket. Are you sure you're calling the 'Bucket' class's constructor from there? It should look like this:
class RenderBucket : public Bucket {
RenderBucket( int a_resX, int a_resY )
: Bucket( a_resX, a_resY )
{
}
}
Initializers in the Bucket class to set the buffer to NULL is a good idea... Also making the Default constructor and copy constructor private will help to make double sure those aren't being used. Remember.. the compiler will create these automatically if you don't:
Bucket(); <-- default constructor
Bucket( int a_resx = 0, int a_resy = 0 ) <-- Another way to make your default constructor
Bucket(const class Bucket &B) <-- copy constructor
You haven't made a private copy constructor, or any default constructor. If class Bucket is constructed via one of these implicitly-defined methods, buffer will either be uninitialized, or it will be a copied pointer made by a copy constructor.
The copy constructor for class Bucket is Bucket(const Bucket &B) -- if you do not explicitly declare a copy constructor, the compiler will generate a "naive" copy constructor for you.
In particular, if this object is assigned, returned, or otherwise copied, the copy constructor will copy the pointer to a new object. Eventually, both objects' destructors will attempt to delete[] the same pointer and the second attempt will be a double deletion, a type of heap corruption.
I recommend you make class Bucket's copy constructor private, which will cause attempted copy construction to generate a compile error. As an alternative, you could implement a copy constructor which allocates new space for the copied buffer.
Exactly the same applies to the assignment operator, operator=.
The need for a copy constructor is one of the 55 tips in Scott Meyer's excellent book, Effective C++: 55 Specific Ways to Improve Your Programs and Designs:
This book should be required reading for all C++ programmers.
If you add:
class Bucket {
/* Existing code as-is ... */
private:
Bucket() { buffer = NULL; } // No default construction
Bucket(const Bucket &B) { ; } // No copy construction
Bucket& operator= (const Bucket &B) {;} // No assignment
}
and re-compile, you are likely to find your problem.
There is also another possibility: If your code contains other uses of new and delete, then it is possible these other uses of allocated memory are corrupting the linked-list structure which defines the heap memory. It is common to detect this corruption during a call to delete, because delete must utilize these data structures.

Resources