|
Post by barryk on Feb 18, 2018 16:51:39 GMT 1
Yes, I will revisit my old BaCon code.
Anyway, I have fixed pup_event_d.bac, it now outputs "eth0" correctly with newline character.
The problem was my low-level string manipulation. It just needed one strdup().
|
|
|
Post by barryk on Feb 18, 2018 17:06:12 GMT 1
I was just reading online docs for strdup(), stating that it uses malloc.
Er, doesn't that mean, if I am in a BaCon code loop, where, say the following is repeatedly called:
buf2_str$=strdup(buf2)
Then, each time around it will assign a new memory buffer, and not release it? So old buffers will accumulate?
|
|
|
Post by Pjot on Feb 18, 2018 18:34:04 GMT 1
Hi barry, Yes, that's correct - multiple subsequent uses of malloc for the same string variable would cause a memory leak. Please install this package, it should solve everything with your pointer assignments. Please let me know your results. Best regards Peter
|
|
|
Post by barryk on Feb 19, 2018 10:49:55 GMT 1
Progress report, using 3.7.2beta. Things have improved, however, we are back to the original problem, that CONCAT$ is broken for string "eth0". It works, and I get "eth0" outputted to /tmp/pup_event_ipc/network_myapp, but no newline. pup_event_dTST2.bac is attached. It has PRINT statements to prove what I am saying: DECLARE outmsg TYPE char*
outmsg_str$=CONCAT$(zipc_event$,"\n") clientfile=clientfile_str$ outmsg=outmsg_str$ IF zipc_event$=="eth0" THEN PRINT "outmsg_str$=",outmsg_str$; PRINT "outmsg=",outmsg; PRINT "the above two should be on separate lines" ENDIF This is what I get: # ./temp1/pup_event_dTST2 outmsg_str$=eth0outmsg=eth0the above two should be on separate lines CONCAT$ appended a newline, so it should print. It works for other strings, but not for "eth0". Attachments:pup_event_dTST2.bac (7.62 KB)
|
|
|
Post by barryk on Feb 19, 2018 10:56:36 GMT 1
If you need more proof:
outmsg_str$=CONCAT$(zipc_event$,"\n") clientfile=clientfile_str$ outmsg=outmsg_str$ IF zipc_event$=="timeout" THEN PRINT "outmsg_str$=",outmsg_str$; PRINT "outmsg=",outmsg; PRINT "the above two should be on separate lines" ENDIF
It is the same function, in this case detecting the four-second timeout, where "timeout" is written to /tmp/pup_event_ipc/timeout4_myapp
But that is incidental. The point is, now CONCAT$ works:
# ./temp1/pup_event_dTST2 outmsg_str$=timeout outmsg=timeout the above two should be on separate lines
|
|
|
Post by barryk on Feb 19, 2018 12:03:34 GMT 1
OK, have done a bit of a dig into my history. The most recent version of BaCon for which I know all my .bac utilities worked, is 3.0.2.
Looking in the changelog, 3.0.3 introduced "string handling improvements".
I have compiled pup_event_d.bac with 3.0.2, it works perfectly. "eth0" prints with a newline. All is well.
|
|
|
Post by Pjot on Feb 19, 2018 20:17:07 GMT 1
Hi barry,
Your last program works for me, and after some tweaking I was able to reproduce the problem.
The reason for the issue again has to do with mixing BaCon's high performance string and pointers. What happens is the following:
(1) You assign the variable 'buf2_str$' some string at line 78:
buf2_str$="................................................................"
The regular string variable now has a pre-buffer which contains the length, set to 64.
(2) Then a reference pointer to this buffer is created at line 79:
buf2=buf2_str$
(3) Then, in your mainloop, there is a lot of C code between USEC/ENDUSEC which fiddles around with the memory area pointed to by 'buf2'.
(4) Lastly, you pass the original 'buf2_str$' variable which still has length 64 to the function 'ipc_post_func', where a newline is concatenated, and of course, the CONCAT$ function will concatenate this at the end of string, meaning at position 64.
(5) The writing of variable 'buf2_str$' will happen until the '0' byte and therefore, there is no newline at the end of the string.
There is no quick solution for this now. Mixing BaCon string variables and memory area hacking will inevitably corrupt the internal administration in pre-buffers which is needed for high performance string manipulation. Similar things will happen in case of other BASIC dialects or with languages like Pascal, for example.
The long-term structural solution is to rewrite the part between USEC/ENDUSEC so it uses genuine BaCon code. I will post a suggestion for this shortly.
Best regards Peter
EDIT: there may be a possibility to invalidate the original string variable for high performance manipulation as soon as it is assigned to a pointer. I will look into this tomorrow.
|
|
|
Post by Pjot on Feb 19, 2018 21:56:21 GMT 1
Hi barry, I have replaced the code starting from line 147 into the following (first lines are the same). This creates the 'eth0' with the newline. HTH Peter IF eventstatus==0 THEN 'one-second timeout.
'do not call /usr/local/pup_event/frontend_timeout directly, use ipc... 'look for any files named /tmp/pup_event_ipc/timeout1_* ... ' except after 4 seconds, will post to "timeout4_" instead... ' and after 60 seconds, will post to "timeout60_" instead... INCR cnt60 INCR cnt4 IF cnt60>=60 THEN ipc_prefix$="timeout60_" cnt60=0 ELIF cnt4>=4 THEN ipc_prefix$="timeout4_" cnt4=0 ELSE ipc_prefix$="timeout1_" ENDIF ipc_post_func(ipc_prefix$,"timeout")
flagactive = 0
OPEN netdir_str$ FOR DIRECTORY AS dip
IF dip <> NULL THEN
REPEAT GETFILE item$ FROM dip
IF item$ <> "." AND item$ <> ".." AND item$ <> "lo" AND item$ <> "tunl0" AND LEN(item$) THEN
buf1_str$ = netdir_str$ & "/" & item$ & "/dormant"
OPEN buf1_str$ FOR READING AS fp READLN data$ FROM fp CLOSE FILE fp
IF data$ = "0" THEN INCR flagactive IF flagactive = 1 THEN buf2_str$ = item$ ELSE buf2_str$ = "" ENDIF ENDIF ENDIF UNTIL LEN(item$) = 0 ENDIF
CLOSE DIRECTORY dip
' Check if need to update network status file... IF FILEEXISTS(net_ifs_str$) THEN netfiledata$ = LOAD$(net_ifs_str$)
IF netfiledata$ != buf2_str$ THEN SAVE buf2_str$ TO net_ifs_str$ 'also post to any ipc clients... ipc_post_func("network_", buf2_str$) ENDIF
CONTINUE ENDIF
|
|
|
Post by Pjot on Feb 19, 2018 23:57:30 GMT 1
Hi barry, The fix is ready, it will simply invalidate a string for high performance manipulations as soon a pointer variable is assigned to that string. You can download the latest beta from here. Please let me know your results (if you have time)? BR Peter
|
|
|
Post by barryk on Feb 20, 2018 23:52:20 GMT 1
Success I haven't tried your substitution for the USEC code yet.
|
|
|
Post by barryk on Feb 21, 2018 0:25:17 GMT 1
Now putting in your replacement for the USEC code.
You have:
INCR flagactive IF flagactive = 1 THEN buf2_str$ = item$ ELSE buf2_str$ = "" ENDIF
Whereas the original C code is:
flagactive=flagactive+1; 'post info to a file... if (flagactive==1) { strcat(buf2,dit->d_name); } else { strcat(buf2," "); strcat(buf2,dit->d_name); }
I presume that it is not OK to do this:
buf2_str$ = buf2_str$ & " " & item$
I can assign to a different string, then back to buf2_str$, but is there a more concise way of doing it?
|
|
|
Post by barryk on Feb 21, 2018 0:41:57 GMT 1
Your code:
OPEN netdir_str$ FOR DIRECTORY AS dip IF dip <> NULL THEN ...
ENDIF CLOSE DIRECTORY dip
Whereas the original C has the "closedir(dip);" inside the IF ... ENDIF.
That is, only close the directory if it succeeded to open.
Also:
buf1_str$ = netdir_str$ & "/" & item$ & "/dormant" OPEN buf1_str$ FOR READING AS fp READLN data$ FROM fp CLOSE FILE fp
Whereas the original C check for successful open:
fp=fopen(buf1,"r"); if (fp!=NULL) { char1=fgetc(fp); fclose(fp);
...
}
And again, only closes if a successful open.
|
|
|
Post by Pjot on Feb 21, 2018 21:52:36 GMT 1
Hi barry,
Good to see that the new beta solves your issues now. Basically, any time a program now assigns a pointer variable to a string, BaCon will mark that string as having an invalid pre-buffer. All string functions which need to determine the length will use a plain 'strlen', as in the previous BaCon versions.
This way, BaCon will be compatible with your code and also maintains the functionality for high-performance processing. I will update the documentation accordingly.
And this is a valid construct:
buf2_str$ = buf2_str$ & " " & item$
I use this kind of concatenation myself all the time. And you can add as many '&' arguments as you like.
Regarding my code proposal, it will take me more time to oversee your code base, and verify the overall consequences for the functionality you're looking for. But I am just trying to show that many USEC constructs now can be replaced with native BaCon code.
Best regards Peter
|
|
|
Post by barryk on Feb 22, 2018 0:35:10 GMT 1
Peter, I greatly appreciate the time that you put into this, solving my problems. Version 3.7.2 is a very important milestone for me, given my perchance for using USEC, and using C functions directly in BaCon code. Good news about that too: buf2_str$ = buf2_str$ & " " & item$ EDIT:Ha ha, that should be " penchant", not " perchance" Dictionary definition of penchant:
|
|
|
Post by Pjot on Feb 22, 2018 19:38:54 GMT 1
Dear barry,
Next days I will do some testing in 3.7.2 and then I am aiming to release BaCon 3.7.2 at March 1.
Please do not hesitate to mention other problems you run into.
Best regards Peter
|
|