LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Can't close Labview when calling external library.

Hi all.  I am calling an external dll and all of the functions etc.. work perfectly. However, when i try to exit Labview (or even a labview application) it hangs and i have to close it using the task manager.  Any ideas ?

thanks!

 

0 Kudos
Message 1 of 14
(2,883 Views)

Tell us more about the external dll, what it does, and how you are calling it. Does it ever return?

0 Kudos
Message 2 of 14
(2,842 Views)

It is called libplctag.  I have compiled for both windows and linux, and i created basic wrapper vi's to call the well documented functions, I dont have this problem using linux, its just windows.

 

Yes, it returns on all functions with expected results. 

0 Kudos
Message 3 of 14
(2,840 Views)

Most likely you’re doing some error in calling the external library. Just because it seems to work doesn’t mean it’s correct. Things to watch out for would be:

 

1) Making sure every datatype configuration matches exactly the used type in the library. Also important for structs!

 

2) Checking all calling conventions. It’s unlikely the problem, as the wrong calling conventions will usually crash the stack and cause immediate problems but parameterless functions called with the wrong calling convention could sometimes cause strange things. 


3) Checking all buffers (strings, arrays) you pass to the function. This is especially important for buffers the external function is expected to write into. Most LabVIEW programmers assume that such buffers are automatically sized to the right size since that is what the managed contract in LabVIEW allows to do. But your external DLL is unmanaged code (unless it was explicitly written for LabVIEW, which your library certainly wasn’t) and no such automatic memory management can happen. Each buffer has to be explicitly preallocated before the call and possibly shrinked to the right size after. Depending on the function implementation, the right allocation size is according to a second  parameter passed to the function, sometimes in number of elements, other times in bytes and possibly in other units like number of sleepless nights of the programmer who wrote that function. Or it’s a constant hopefully documented in the prosa of the library documentation.

 

Number 3) is without doubt the single most failure when someone uses the Call Library Node and I have seen it happen many times even from experienced C programmers!

 

Possible errors from the resulting memory corruption are one or more of the following:

- immediate crash

- the very popular error 1097 returned from the call library node

- wrong (but often almost undetectable) results elsewhere in the LabVIEW program when the corruption caused data in a wire to be altered

- a crash sometimes later (minutes to hours and more is possible) when your program causes LabVIEW to access data structures that the bad CLN call corrupted up to a crash when you exit LabVIEW as it tries to clean up everything and trips over the wire laid out by that bad CLN call

- and last but not least getting caught in an endless loop as it tries to cleanup the corrupted memory at exit

Rolf Kalbermatter
My Blog
Message 4 of 14
(2,794 Views)

Thanks for the reply.  (The SDK uses simple datatypes, so dont have to worry about structures etc...)

I have tried a few different things and still have not been able to figure out the problem.  Happens in both 32bit and 64bit.  I have narrowed it down to the create_tag function call. 

If i run this vi, i cannot close labview.  For the AttributeString parameter i have tried using a C string pointer (Which works as far as getting the correct returns), and also a byte array, which also works.  Not really sure what else to try at this point.

I have attached a simple test case that calls the create_tag function from the .dll.  If you link the .dll, and run it you should get an error code back since that PLC will not exist on your network.  At that point try and close labview.

Any ideas?

Thanks!

 

Here is the SDK  function

int32_t plc_tag_create(const char *attrib_str, int timeout);

And here is a link to the API documentation

https://github.com/kyle-github/libplctag/wiki/API

 

0 Kudos
Message 5 of 14
(2,786 Views)

The C string parameter is a read only input parameter (at least the documentation would make you believe so and I'm not assuming for now that some function inside that call tries to write into that buffer) so the standard configuration in the CLN to pass this as a C String Pointer should be fine.

 

If your observation that this function causes things to block is correct, that would strongly suggest that this function is somewhere installing an exit hook or something similar that prevents the process from shutting down. I had a quick look and see that the library spins up threads internally to monitor the tag processing, so there is a good chance that it actually does something like that to prevent the threads from trying to access data that has been getting invalid during tear down of the process. It shouldn't be necessary as process shutdown in Windows usually also suspends any threads inside the process that might still be running, but you never know for sure and I really have no time to analize the whole library for now.

 

Are you sure you called the plc_tag_destroy(int32_t tag) function for every single tag you created during the execution of your program? If you already do that, make sure you call this function in the according VI independent of any incoming error. Resource cleanup functions should always execute, no matter if there was a previous error (and include some proper checks for invalid handles, resource identifiers or such to avoid crashing on them if they never were created or already got invalidated before).

 

If this solves the problem, the library is basically not fool proof. It should somehow remember all created tags and in the DLLMain() handler for shutdown processing of DLL_PROCESS_DEATTACH, properly destroy all those tags itself.

 

If it doesn't help, there might to be some other cleanup function that also needs to be called before attempting to shutdown a process.

Rolf Kalbermatter
My Blog
Message 6 of 14
(2,760 Views)

Thanks again for the reply.  Yes, i always make sure to destroy each tag created.  Makes no difference.  I will contact the developer to see if there might be another cleanup function I'm missing.

thanks!

 

 

0 Kudos
Message 7 of 14
(2,749 Views)

If i set the parameter to a Constant C string pointer, as is suggested in the SDK it seems to work.

DLL call.png

 
G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 8 of 14
(2,745 Views)

The first call took like 10 secs, but then i have nothing on your route-address. Changing to localhost gave the same -32 result directly.

 

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 9 of 14
(2,740 Views)

@Yamaeda wrote:

If i set the parameter to a Constant C string pointer, as is suggested in the SDK it seems to work.


That might be just a side effect. Changing that checkbox is only an indication to the LabVIEW inplace optimizer that the function does not modify the parameter (and has consequently no function for parameters passed by value eventhough you can uncheck it there if you want), and should not change anything fundamentally about the parameter.

Due to the possible different optimization of memory allocations in resulting changes in the clumper algorithme the resulting code execution can change but that should not let the library have any influence on the ability of LabVIEW to shutdown properly (or anything else for that matter). It is not like LabVIEW would allocate that memory buffer with a write protection set in the CPU registers.

Rolf Kalbermatter
My Blog
0 Kudos
Message 10 of 14
(2,738 Views)