UBE ending in Error Status

Gov

Guest
UBE ending in Error Status - C BSFN crashes

Hello

I have a custom UBE which always ending in error status on server. This works fine on a FAT client. Tricky part is neither jde.log or debug.log shows any error or exception. And Debug log ends at a an API of C BSFN and doesnt say any error message. Is there any way to findout whats going wrong?

UBE is running on a WINDOWS server.

Thanks,
 
Last edited by a moderator:

JMR

VIP Member
Is the BSFN a custom BSFN?
If not, what object/function are you calling?
If so, post the code.
 

Gov

Guest
it is custom c BSFN. please find attached code.

this whole process working fine until some time back. It started failing on server recently, but still works using FAT client.
 

Attachments

  • B59IA002.zip
    7.5 KB · Views: 12
Last edited by a moderator:

sselman

Well Known Member
My first check would be does the JDE account have access to the file or folder. Maybe someone changed the file level security.
 

JMR

VIP Member
A lot going on in there and tough for 'new' eyes to make much of it just by eyeballing the code. It might be helpful to see the .h, too. Although I am not sure I have much more to offer. I will leave you with a few things that popped out, but I don't have a lot of confidence they are your culprit.

Code:
                        while ((idJDBReturn = JDB_Fetch(hRequestF59IA003, (void *)&dsInternal.f59ia003[iNext], (int)NULL)) == JDEDB_PASSED)
                        {
                            iNext++;
                        }/*End While*/

This is potentially dangerous. I can't see your definition of dsInternal, but there is potential for memory violation here. I presume you tested on the server with the same input that works on the fat, so this is probably not your issue

Code:
                            /* IAA Wave 2 03/04/14*/                           
                           [COLOR=#ff0000] /* nIndex is losing value for some reason. Store it in a variable and re assign*/[/COLOR]
                            nIndex_Dup = nIndex;
                            /* End IAA Wave 2*/

This comment is a bit disconcerting. A variable should not just 'lose' its value. This is a good indication that something is inadvertently overwriting those contents...not good!

Code:
                            {   
                                    [COLOR=#ff0000]Internal2.pSegment = (JCHAR *)_J(" ");[/COLOR]
                                    Internal2.iMappingType = nMappingType;
                                    Internal2.iValidationON = jdeAtoi(dsInternal.f59ia003[iCounter].imurcd);
                                    idJDEDBReturn    =    I59IA002_AssignValuetoColumn (lpBhvrCom, hRequestTable,    lpVoid,    &Internal2);
                                    if (idJDEDBReturn == ER_ERROR)
                                    {
                                        goto ProcessNextRecord;
                                    }
                                }

I am not sure about my comments here. I wonder if the memory pointed to by Internal2.pSegment will ALWAYS be valid in the I59IA002_AssignValuetoColumn function. I tend to think it should be valid for the entirety of the brackets in which the _J(" ") is allocated, but may be something someone else can comment on.


My suggestion would be to insert a bunch of jdeWriteLogEntry lines into the code to narrow down where exactly it's failing. Too much to look at right now.
 

peterbruce

Legendary Poster
Gov,

In line with Sean's comment, what changed on the server when the UBE/BSFN began to fail? My guess is that if it was working and then stopped working properly, something changed. If the UBE and BSFN were not changed (it still works on the fat client, so probably not), then something on the server changed that caused the problem.
 

BOster

Legendary Poster
I think Jeremy has definitely pointed out some red flags in the code that you may want to re-think. If dsInternal.f59ia003 is a statically sized array... that's a time bomb waiting to go off. If you want to store a list of table records in an array like that you should really dynamically (re)allocate memory as records are read or use the jde LINKLIST api - no one ever mentions the jde LINKLIST api but it's actually very useful for things like this.

One thing I will say, is that I have had, on multiple occasions had things (C code) work fine locally but not on the server. The bugs in my C code didn't manifest themselves until ran on a server. Usually something like not initializing a variable when declared... something like a string that locally initialized with a null term because I got lucky so all my string manip calls worked just fine locally but on the server when initialized with junk data caused a buffer overflow or something like that. You may have to debug on the server to find it, which is what I have usually had to do in the past.
 

JMR

VIP Member
Code:
{
        [COLOR=#ff0000]Internal2.pSegment = (JCHAR *)_J(" ");[/COLOR]
        Internal2.iMappingType = nMappingType;
        Internal2.iValidationON = jdeAtoi(dsInternal.f59ia003[iCounter].imurcd);
        idJDEDBReturn    =    I59IA002_AssignValuetoColumn (lpBhvrCom, hRequestTable,    lpVoid,    &Internal2);
        if (idJDEDBReturn == ER_ERROR)
        {
            goto ProcessNextRecord;
        }
    }


One more thought on this piece of code. While I am not positive on exactly how much memory would be allocated in the statement in red, my bet is that is would allocate 2 JCHAR characters (1 for the blank space and one for the terminating character ) = 4 bytes.

So you have to ask yourself: will this piece of code ever get executed and, in I59IA002_AssignValuetoColumn(), will there ever be a case where more than 4 bytes are copied to the Internal2.pSegment pointer? If the answer is yes, you found at least one offending piece of code. This scenario will violate memory space that was not allocated to Internal2.pSegment.

Code:
                            [COLOR=#ff0000]memset((void *)(&Internal2.lpDDItem), (int)(_J('\0')), sizeof(Internal2.lpDDItem));[/COLOR]                            
                            memset((void *)(&Internal2.zDbRef), (int)(_J('\0')), sizeof(Internal2.zDbRef));
                            [COLOR=#ff0000]memcpy(&Internal2.lpDDItem, &lpDDItem, sizeof(Internal2.lpDDItem));[/COLOR]
                            memcpy(&Internal2.zDbRef, &zDbRef, sizeof(Internal2.zDbRef));


There is a lot of pointer and memory manipulation in this function. Understanding these concepts is paramount when performing so much of this type of coding. The lines in red lead me to believe the author doesn't fully understand the concepts. While I can't say for sure, I would venture the intent was to copy the contents pointed to by lpDDItem into the structure pointed to by Internal2.lpDDItem (which would be bad since this is an unallocated pointer). The following is really what is happening and it just happens to work as desired:

Code:
  [COLOR=#333333]Internal2.lpDDItem = NULL;     [/COLOR][COLOR=#008000]// memset((void *)(&Internal2.lpDDItem), (int)(_J('\0')), sizeof(Internal2.lpDDItem));  [/COLOR][COLOR=#333333]
  Internal2.lpDDItem = lpDDItem;  [/COLOR][COLOR=#008000]// memcpy(&Internal2.lpDDItem, &lpDDItem, sizeof(Internal2.lpDDItem));[/COLOR]
 
Last edited:

Gov

Guest
My first check would be does the JDE account have access to the file or folder. Maybe someone changed the file level security.

Sean, the file was accessible. As per logs it was bouncing after reading the file.
 

Gov

Guest
Thanks Jeremy. It is awesome to come-up with so many helpful insights.

A lot going on in there and tough for 'new' eyes to make much of it just by eyeballing the code. It might be helpful to see the .h, too. Although I am not sure I have much more to offer. I will leave you with a few things that popped out, but I don't have a lot of confidence they are your culprit.

Code:
                        while ((idJDBReturn = JDB_Fetch(hRequestF59IA003, (void *)&dsInternal.f59ia003[iNext], (int)NULL)) == JDEDB_PASSED)
                        {
                            iNext++;
                        }/*End While*/

This is potentially dangerous. I can't see your definition of dsInternal, but there is potential for memory violation here. I presume you tested on the server with the same input that works on the fat, so this is probably not your issue

This piece of code is always on my mind expecting weird results. So far working fine. I see some garbage values loaded when there is smaller table structure used. I am thinking of replacing this code with linked list as Brian recommended.

Code:
                            /* IAA Wave 2 03/04/14*/                           
                           [COLOR=#ff0000] /* nIndex is losing value for some reason. Store it in a variable and re assign*/[/COLOR]
                            nIndex_Dup = nIndex;
                            /* End IAA Wave 2*/

This comment is a bit disconcerting. A variable should not just 'lose' its value. This is a good indication that something is inadvertently overwriting those contents...not good!

It was a while ago, happening in my debugging. I am not focusing this part as it is working functionally for now.

Code:
                            {   
                                    [COLOR=#ff0000]Internal2.pSegment = (JCHAR *)_J(" ");[/COLOR]
                                    Internal2.iMappingType = nMappingType;
                                    Internal2.iValidationON = jdeAtoi(dsInternal.f59ia003[iCounter].imurcd);
                                    idJDEDBReturn    =    I59IA002_AssignValuetoColumn (lpBhvrCom, hRequestTable,    lpVoid,    &Internal2);
                                    if (idJDEDBReturn == ER_ERROR)
                                    {
                                        goto ProcessNextRecord;
                                    }
                                }

I am not sure about my comments here. I wonder if the memory pointed to by Internal2.pSegment will ALWAYS be valid in the I59IA002_AssignValuetoColumn function. I tend to think it should be valid for the entirety of the brackets in which the _J(" ") is allocated, but may be something someone else can comment on.

I made major changes to my program. I took out Internal2 structure and removed all the copy statements. This got better and now back to working status. In my initial testing today the program is working as it was earlier.

My suggestion would be to insert a bunch of jdeWriteLogEntry lines into the code to narrow down where exactly it's failing. Too much to look at right now.

Thanks for this recommendation. I used jdeWriteLogEntry after every statement to see where it is bouncing.
 

Gov

Guest
I think Jeremy has definitely pointed out some red flags in the code that you may want to re-think. If dsInternal.f59ia003 is a statically sized array... that's a time bomb waiting to go off. If you want to store a list of table records in an array like that you should really dynamically (re)allocate memory as records are read or use the jde LINKLIST api - no one ever mentions the jde LINKLIST api but it's actually very useful for things like this.

One thing I will say, is that I have had, on multiple occasions had things (C code) work fine locally but not on the server. The bugs in my C code didn't manifest themselves until ran on a server. Usually something like not initializing a variable when declared... something like a string that locally initialized with a null term because I got lucky so all my string manip calls worked just fine locally but on the server when initialized with junk data caused a buffer overflow or something like that. You may have to debug on the server to find it, which is what I have usually had to do in the past.

Brian, Thanks for this advice. I am novice to Linkedlist API. I will do little bit research to replace my code. And to answer your question, it is defined as statically sized array.
 

Gov

Guest
Code:
{
        [COLOR=#ff0000]Internal2.pSegment = (JCHAR *)_J(" ");[/COLOR]
        Internal2.iMappingType = nMappingType;
        Internal2.iValidationON = jdeAtoi(dsInternal.f59ia003[iCounter].imurcd);
        idJDEDBReturn    =    I59IA002_AssignValuetoColumn (lpBhvrCom, hRequestTable,    lpVoid,    &Internal2);
        if (idJDEDBReturn == ER_ERROR)
        {
            goto ProcessNextRecord;
        }
    }


One more thought on this piece of code. While I am not positive on exactly how much memory would be allocated in the statement in red, my bet is that is would allocate 2 JCHAR characters (1 for the blank space and one for the terminating character ) = 4 bytes.

So you have to ask yourself: will this piece of code ever get executed and, in I59IA002_AssignValuetoColumn(), will there ever be a case where more than 4 bytes are copied to the Internal2.pSegment pointer? If the answer is yes, you found at least one offending piece of code. This scenario will violate memory space that was not allocated to Internal2.pSegment.


Most of this code is removed. I felt unnecessary.


Code:
                            [COLOR=#ff0000]memset((void *)(&Internal2.lpDDItem), (int)(_J('\0')), sizeof(Internal2.lpDDItem));[/COLOR]                            
                            memset((void *)(&Internal2.zDbRef), (int)(_J('\0')), sizeof(Internal2.zDbRef));
                            [COLOR=#ff0000]memcpy(&Internal2.lpDDItem, &lpDDItem, sizeof(Internal2.lpDDItem));[/COLOR]
                            memcpy(&Internal2.zDbRef, &zDbRef, sizeof(Internal2.zDbRef));


There is a lot of pointer and memory manipulation in this function. Understanding these concepts is paramount when performing so much of this type of coding. The lines in red lead me to believe the author doesn't fully understand the concepts. While I can't say for sure, I would venture the intent was to copy the contents pointed to by lpDDItem into the structure pointed to by Internal2.lpDDItem (which would be bad since this is an unallocated pointer). The following is really what is happening and it just happens to work as desired:

Code:
  [COLOR=#333333]Internal2.lpDDItem = NULL;     [/COLOR][COLOR=#008000]// memset((void *)(&Internal2.lpDDItem), (int)(_J('\0')), sizeof(Internal2.lpDDItem));  [/COLOR][COLOR=#333333]
  Internal2.lpDDItem = lpDDItem;  [/COLOR][COLOR=#008000]// memcpy(&Internal2.lpDDItem, &lpDDItem, sizeof(Internal2.lpDDItem));[/COLOR]

Most of memory copy code is replaced. Today i felt like that code can be simplified or not required. This increased performance of the program as well.

The lines in red lead me to believe the author doesn't fully understand the concepts.

:D totally agree. I know the author. He was novice when he started this program 2 years back. the whole idea and design inspired to program, even though he is not good at c programming. Got a shape and working condition, but dont know even now the complete concepts of C :D

Thanks for all your insights and ideas. These comments made me to correct the issue.

Thanks again!
 

JMR

VIP Member

quote_icon.png
Originally Posted by JMR

Code:
    /* IAA Wave 2 03/04/14*/                                   
        [COLOR=#ff0000]/* nIndex is losing value for some reason. Store it in a variable and re assign*/[/COLOR]
        nIndex_Dup = nIndex;
        /* End IAA Wave 2*/

It was a while ago, happening in my debugging. I am not focusing this part as it is working functionally for now.

I would still be concerned about the 'patch' that was used to allow this code to work. I didn't explicitly state this earlier, but you really need to remove the 'patch' (copying the variable and reassigning it when it loses value). The patch is only hiding a deeper memory issue that really needs to be figured out. Hopefully all the changes you've made have fixed any/all memory issues, but you really, really need to remove that patch. If, after you remove that patch, you still have the same issue with that variable, then I would set a conditional breakpoint on the contents of that variable changing... that should point you to the actual line of code that is causing the memory violation.

Remove that patch!
 

Gov

Guest
I would still be concerned about the 'patch' that was used to allow this code to work. I didn't explicitly state this earlier, but you really need to remove the 'patch' (copying the variable and reassigning it when it loses value). The patch is only hiding a deeper memory issue that really needs to be figured out. Hopefully all the changes you've made have fixed any/all memory issues, but you really, really need to remove that patch. If, after you remove that patch, you still have the same issue with that variable, then I would set a conditional breakpoint on the contents of that variable changing... that should point you to the actual line of code that is causing the memory violation.

Remove that patch!
that's good way to test current code change. I removed patch and had a test using FAT client. It worked with no issues. I will give a test on server as well to be sure.
 
Top