Difference between revisions of "Issues & workarounds"
DaveRabelink (Talk | contribs) (Added info on DynalibChecker tool) |
DaveRabelink (Talk | contribs) m |
||
(3 intermediate revisions by one user not shown) | |||
Line 1: | Line 1: | ||
− | + | {{PageHeader|Dynalib issues & workarounds}} | |
+ | |||
__TOC__ | __TOC__ | ||
− | + | ||
<!------------------------------------------------------------------------------------------------------------------------------> | <!------------------------------------------------------------------------------------------------------------------------------> | ||
{{TipHeader|Issue : case sensitive dynalib filenames}} | {{TipHeader|Issue : case sensitive dynalib filenames}} | ||
<b>Defect ID : TD-345</b><br> | <b>Defect ID : TD-345</b><br> | ||
− | + | ||
<b>Symptoms</b><br> | <b>Symptoms</b><br> | ||
Line 18: | Line 19: | ||
* Dynalibs can not find their own qualified references | * Dynalibs can not find their own qualified references | ||
* Code which should be executed once (e.g. at initialisation or closing) are called multiple times | * Code which should be executed once (e.g. at initialisation or closing) are called multiple times | ||
− | + | ||
+ | |||
This bug seems to be present in all TD versions.<br> | This bug seems to be present in all TD versions.<br> | ||
+ | |||
<b>Cause</b><br> | <b>Cause</b><br> | ||
Normally, the way include items are declared does not matter.<br> | Normally, the way include items are declared does not matter.<br> | ||
If you include a normal library using Base.apl or BASE.apl, Team Developer treats them equally.<br> | If you include a normal library using Base.apl or BASE.apl, Team Developer treats them equally.<br> | ||
− | + | ||
+ | |||
But there is a bug how TD treats including Dynalibs at runtime.<br> | But there is a bug how TD treats including Dynalibs at runtime.<br> | ||
Seems Dynalib1.apd is not the same as DYNALIB1.apd (mind the case difference).<br> | Seems Dynalib1.apd is not the same as DYNALIB1.apd (mind the case difference).<br> | ||
Line 30: | Line 34: | ||
different case in the filename. A dynalib should be loaded only once in the system !<br> | different case in the filename. A dynalib should be loaded only once in the system !<br> | ||
TD thinks the dynalibs are not the same. This results in multiple runtime instances of the same dynalib.<br> | TD thinks the dynalibs are not the same. This results in multiple runtime instances of the same dynalib.<br> | ||
− | + | ||
+ | |||
[[Image:DynalibStruct2.png]] | [[Image:DynalibStruct2.png]] | ||
− | + | ||
+ | |||
<b>Remedy/workaround</b><br> | <b>Remedy/workaround</b><br> | ||
Check your complete application structure and be sure all dynalibs are included with the same case for the filename.<br> | Check your complete application structure and be sure all dynalibs are included with the same case for the filename.<br> | ||
See picture for a visual explanation. The red include line is wrong. Dynalib2.apd includes Dynalib1.apd using a different<br> | See picture for a visual explanation. The red include line is wrong. Dynalib2.apd includes Dynalib1.apd using a different<br> | ||
case for the filename compared to the Executable.<br> | case for the filename compared to the Executable.<br> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | At runtime Dynalib1.apd is loaded twice. So when the executable has initialized its own instance of Dynalib1.apd<br> | ||
+ | (the dynalib has loaded some data and holds it), Dynalib2.apd expects an initialized dynalib. But in fact Dynalib2.apd<br> | ||
+ | has its own instance which will be initialized again.<br> | ||
+ | |||
+ | |||
+ | <sub>So it is not the case of the filename itself (the physical filename on disc), but the way the dynalib name | ||
+ | is spelled in the include section of your sources.</sub> | ||
Line 69: | Line 75: | ||
<br> | <br> | ||
Another workaround is to manually set all UDV's involved to NULL in the dynalibs just before closing the application. | Another workaround is to manually set all UDV's involved to NULL in the dynalibs just before closing the application. | ||
− | |||
− | |||
Line 76: | Line 80: | ||
{{TipHeader|Issue : SalCompileAndEvaluate: the performance of the build varies between each build of the dynalib}} | {{TipHeader|Issue : SalCompileAndEvaluate: the performance of the build varies between each build of the dynalib}} | ||
<b>Defect ID : 83056</b><br> | <b>Defect ID : 83056</b><br> | ||
− | + | ||
<b>Symptoms</b><br> | <b>Symptoms</b><br> | ||
Line 83: | Line 87: | ||
During execution the CPU of the PC is getting to 100% which locks the PC and a hard reset could be the<br> | During execution the CPU of the PC is getting to 100% which locks the PC and a hard reset could be the<br> | ||
only way to stop the application.<br> | only way to stop the application.<br> | ||
− | + | ||
+ | |||
This bug seems to be present in TD3.x<br> | This bug seems to be present in TD3.x<br> | ||
It is solved in TD42 (fixed defect ID 83056, see notes on TD42 fixes).<br> | It is solved in TD42 (fixed defect ID 83056, see notes on TD42 fixes).<br> | ||
− | + | ||
+ | |||
<b>Cause</b><br> | <b>Cause</b><br> | ||
Seems the symbol table of the dynalib is messing up the total symbol table of the application<br> | Seems the symbol table of the dynalib is messing up the total symbol table of the application<br> | ||
which causes the slowdown.<br> | which causes the slowdown.<br> | ||
− | + | ||
+ | |||
<b>Remedy/workaround</b><br> | <b>Remedy/workaround</b><br> | ||
A simple workaround is to force the application to freshen up the symbol table of the main executable<br> | A simple workaround is to force the application to freshen up the symbol table of the main executable<br> | ||
Line 97: | Line 104: | ||
which actions are performed in the call. When the main application executes the command, all injected<br> | which actions are performed in the call. When the main application executes the command, all injected<br> | ||
dynalibs which uses SalCompileAndEvaluate will work in full speed.<br> | dynalibs which uses SalCompileAndEvaluate will work in full speed.<br> | ||
− | + | ||
+ | |||
Here a sample of a dummy call | Here a sample of a dummy call | ||
Line 124: | Line 132: | ||
Call PALForceDynalibIntegrity( ) | Call PALForceDynalibIntegrity( ) | ||
</pre> | </pre> | ||
− | + | ||
− | Here you can download the sourcecode for the function: | + | |
− | + | Here you can download the sourcecode for the function:<br> | |
+ | {{Download | ||
+ | |URL=http://samples.tdcommunity.net/index.php?dir=&file=WIKI_ForceDynalibIntegrity.zip | ||
+ | |TEXT=WIKI_ForceDynalibIntegrity.zip | ||
+ | }} | ||
<!------------------------------------------------------------------------------------------------------------------------------> | <!------------------------------------------------------------------------------------------------------------------------------> | ||
{{TipHeader|Issue : Formats/input masks do not work on dynalib top level windows}} | {{TipHeader|Issue : Formats/input masks do not work on dynalib top level windows}} | ||
− | + | ||
<b>Symptoms</b><br> | <b>Symptoms</b><br> | ||
When using top level windows (forms, dialog boxes etc) from dynalibs, formats/input masks defined on fields within the dynalib top level windows do not work.<br> | When using top level windows (forms, dialog boxes etc) from dynalibs, formats/input masks defined on fields within the dynalib top level windows do not work.<br> | ||
When trying to enter data into the fields, these issues could emerge :<br> | When trying to enter data into the fields, these issues could emerge :<br> | ||
− | + | ||
+ | |||
*All data can be entered, the formats and input masks seem not to be present | *All data can be entered, the formats and input masks seem not to be present | ||
*Data can not be entered, the field seems to be locked | *Data can not be entered, the field seems to be locked | ||
*A GPF occurs when entering data into the field | *A GPF occurs when entering data into the field | ||
− | + | ||
<b>Cause</b><br> | <b>Cause</b><br> | ||
When the list of formats/input masks in the main application differs from those defined in the dynalib, TD seems not to make the dynalib formats available<br> | When the list of formats/input masks in the main application differs from those defined in the dynalib, TD seems not to make the dynalib formats available<br> | ||
to the main application. So the main application only uses the formats/input masks defined within the main source only.<br> | to the main application. So the main application only uses the formats/input masks defined within the main source only.<br> | ||
− | + | ||
<b>Remedy/workaround</b><br> | <b>Remedy/workaround</b><br> | ||
Line 152: | Line 165: | ||
Also the sequence of formats is important. So it is best to copy/paste the complete section.<br> | Also the sequence of formats is important. So it is best to copy/paste the complete section.<br> | ||
<br> | <br> | ||
− | Here you can download a sample: | + | Here you can download a sample:<br> |
− | + | {{Download | |
− | + | |URL=http://samples.tdcommunity.net/index.php?dir=&file=WIKI_ShowAndFixDynalibFormatsBug.zip | |
+ | |TEXT=WIKI_ShowAndFixDynalibFormatsBug.zip | ||
+ | }} | ||
+ | |||
<!------------------------------------------------------------------------------------------------------------------------------> | <!------------------------------------------------------------------------------------------------------------------------------> | ||
{{TipHeader|Locate dynalib issues using DynalibChecker}} | {{TipHeader|Locate dynalib issues using DynalibChecker}} | ||
− | It is wise to check your sources for the issues described in this section to be sure you won't get strange | + | |
+ | New version 1.1 available.<br> | ||
+ | - Much faster operation<br> | ||
+ | - Workaround for CDK memory leak bug<br> | ||
+ | - Now in TD 1.5.1 source format (TD 1.x) and TD4.2 (and higher, also TD60 WIN32)<br> | ||
+ | |||
+ | |||
+ | It is wise to check your sources for the issues described in this section to be sure you won't get strange behavior.<br> | ||
Correcting them accordingly will result in a more stable system.<br> | Correcting them accordingly will result in a more stable system.<br> | ||
− | + | ||
+ | |||
Since I began using dynalibs I discovered these issues along the way, but it is a hard task<br> | Since I began using dynalibs I discovered these issues along the way, but it is a hard task<br> | ||
to check for them when the application gets bigger.<br> | to check for them when the application gets bigger.<br> | ||
− | But it is needed, because when the workarounds are applied, a system | + | But it is needed, because when the workarounds are applied, a system utilizing dynalibs is highly stable.<br> |
− | + | ||
+ | |||
On one application which uses more than 70 dynalibs, I decided to create a CDK tool to automate checking the sources.<br> | On one application which uses more than 70 dynalibs, I decided to create a CDK tool to automate checking the sources.<br> | ||
It is used regularly and finds the issues quickly and gives a more precise way to pinpoint the faulty locations.<br> | It is used regularly and finds the issues quickly and gives a more precise way to pinpoint the faulty locations.<br> | ||
− | + | ||
+ | |||
So here I post the tool, named Dynalib Checker, for public use.<br> | So here I post the tool, named Dynalib Checker, for public use.<br> | ||
It is an application using CDK. The source is included.<br> | It is an application using CDK. The source is included.<br> | ||
− | + | ||
+ | |||
A readme textfile is included in the archive with more info. | A readme textfile is included in the archive with more info. | ||
Here the download link for the tool:<br> | Here the download link for the tool:<br> | ||
− | + | {{Download | |
− | + | |URL=http://samples.tdcommunity.net/index.php?dir=&file=DynalibCheckerV11.zip | |
− | + | |TEXT=DynalibCheckerV11.zip | |
− | + | }} | |
− | + | ||
+ | |||
+ | [[Image:DynalibChecker_Classes.gif]] | ||
[[Category:Dynalibs]] | [[Category:Dynalibs]] |
Latest revision as of 10:43, 15 July 2013
Dynalib issues & workarounds
Issue : case sensitive dynalib filenames 
Defect ID : TD-345
Symptoms
When the application uses several dynalibs which are included at several levels
(so dynalibs include each other and use several different entry points) these symptoms
could emerge :
- Initialised dynalibs seems to loose their data
- Windows are created multiple times, but logically they should not
- Dynalibs can not find their own qualified references
- Code which should be executed once (e.g. at initialisation or closing) are called multiple times
This bug seems to be present in all TD versions.
Cause
Normally, the way include items are declared does not matter.
If you include a normal library using Base.apl or BASE.apl, Team Developer treats them equally.
But there is a bug how TD treats including Dynalibs at runtime.
Seems Dynalib1.apd is not the same as DYNALIB1.apd (mind the case difference).
At runtime, TD loads the dynalib multiple times when the dynalib is included at several levels with
different case in the filename. A dynalib should be loaded only once in the system !
TD thinks the dynalibs are not the same. This results in multiple runtime instances of the same dynalib.
Remedy/workaround
Check your complete application structure and be sure all dynalibs are included with the same case for the filename.
See picture for a visual explanation. The red include line is wrong. Dynalib2.apd includes Dynalib1.apd using a different
case for the filename compared to the Executable.
At runtime Dynalib1.apd is loaded twice. So when the executable has initialized its own instance of Dynalib1.apd
(the dynalib has loaded some data and holds it), Dynalib2.apd expects an initialized dynalib. But in fact Dynalib2.apd
has its own instance which will be initialized again.
So it is not the case of the filename itself (the physical filename on disc), but the way the dynalib name
is spelled in the include section of your sources.
Issue : application crashes when it closes 
Symptoms
The application crashes during close generating a GPF or memory read/write error.
This bug seems to be present in all TD versions.
Cause
When the application uses several dynalibs which contain classes with class variables and they are used
by more than one dynalib in the system, TD could release the memory wrongly.
Every dynalib should be totally shielded from other dynalibs as a blackbox. Classes within a dynalib
can not be exported and should not be available to the outside. But TD at runtime seems to get confused when
multiple dynalibs declare the same classname with class variables. When TD releases the memory, it releases
it twice or releases the wrong memory size. This will get TD to crash at close.
Remedy/workaround
Check your complete application structure and be sure all dynalibs are using unique classnames OR be sure
that when you declare classes with the same names spread over dynalibs, they are identical in structure.
So the sequence and contents of the class attributes should be equal.
Another workaround is to manually set all UDV's involved to NULL in the dynalibs just before closing the application.
Issue : SalCompileAndEvaluate: the performance of the build varies between each build of the dynalib 
Defect ID : 83056
Symptoms
Calling SalCompileAndEvaluate in a dynalib seems to get very slow depending of the dynalib build.
The performance could be a few percentages slower or in worse cases could take minutes for one call.
During execution the CPU of the PC is getting to 100% which locks the PC and a hard reset could be the
only way to stop the application.
This bug seems to be present in TD3.x
It is solved in TD42 (fixed defect ID 83056, see notes on TD42 fixes).
Cause
Seems the symbol table of the dynalib is messing up the total symbol table of the application
which causes the slowdown.
Remedy/workaround
A simple workaround is to force the application to freshen up the symbol table of the main executable
which will totally solve the performance issues.
To do this, the main executable should call a SalCompileAndEvaluate at startup. It does not matter
which actions are performed in the call. When the main application executes the command, all injected
dynalibs which uses SalCompileAndEvaluate will work in full speed.
Here a sample of a dummy call
Function: PALForceDynalibIntegrity Local variables String: saTest[*] Number: nError Number: nDummy Number: nCount String: sDummy Date/Time: dtDummy Window Handle: hWndDummy Actions Set nCount = 0 While nCount < 5 Call SalCompileAndEvaluate( "Set saTest[" || SalNumberToStrX( nCount, 0 ) || "] = '" || SalNumberToStrX( nCount, 0 ) || "'", nError, nDummy, nDummy, sDummy, dtDummy, hWndDummy, FALSE, SalContextCurrent( ) ) Set nCount = nCount + 1
Now call the function at application startup (in main executable) :
Application Actions On SAM_AppStartup Call PALForceDynalibIntegrity( )
Here you can download the sourcecode for the function:
WIKI_ForceDynalibIntegrity.zip
Issue : Formats/input masks do not work on dynalib top level windows 
Symptoms
When using top level windows (forms, dialog boxes etc) from dynalibs, formats/input masks defined on fields within the dynalib top level windows do not work.
When trying to enter data into the fields, these issues could emerge :
- All data can be entered, the formats and input masks seem not to be present
- Data can not be entered, the field seems to be locked
- A GPF occurs when entering data into the field
Cause
When the list of formats/input masks in the main application differs from those defined in the dynalib, TD seems not to make the dynalib formats available
to the main application. So the main application only uses the formats/input masks defined within the main source only.
Remedy/workaround
You need to make the dynalib(s) formats section equal to the main application formats section.
Copy all needed formats from the dynalib and place them into the formats section of the main application.
Also the sequence of formats is important. So it is best to copy/paste the complete section.
Here you can download a sample:
WIKI_ShowAndFixDynalibFormatsBug.zip
Locate dynalib issues using DynalibChecker 
New version 1.1 available.
- Much faster operation
- Workaround for CDK memory leak bug
- Now in TD 1.5.1 source format (TD 1.x) and TD4.2 (and higher, also TD60 WIN32)
It is wise to check your sources for the issues described in this section to be sure you won't get strange behavior.
Correcting them accordingly will result in a more stable system.
Since I began using dynalibs I discovered these issues along the way, but it is a hard task
to check for them when the application gets bigger.
But it is needed, because when the workarounds are applied, a system utilizing dynalibs is highly stable.
On one application which uses more than 70 dynalibs, I decided to create a CDK tool to automate checking the sources.
It is used regularly and finds the issues quickly and gives a more precise way to pinpoint the faulty locations.
So here I post the tool, named Dynalib Checker, for public use.
It is an application using CDK. The source is included.
A readme textfile is included in the archive with more info.
Here the download link for the tool:
DynalibCheckerV11.zip