NSLogWriter ArgumentOutOfRangeException - exception

As you can see in the attached screenshot, I am checking the length of sb and if it's not 0, it will execute the Replace command.
However, somehow the Length is zero and it is executing the Replace command and throwing an exceptiong. But there is content in '_str', so I don't understand how the length could be zero...
Is this a bug in StringBuilder?
Below is another bug, probably related to the one above. You can see that I commented out the Replace command and now it is failing on ToString().

How are you using NSLogWriter ? Like this (see my blog):
Console.SetOut (new NSLogWriter ());
Console.WriteLine ("we're back in action!");
or are you creating (and using) your own instance ? e.g.
var log = new NSLogWriter ();
log.WriteLine ("uho");
If you use the second way then you need to handle multithreading yourself. E.g. another log could have flushed (and cleared sb) between the Length check and the Replace call.
System.Console avoids this because the NSLogWriter is wrapped with TextWriter.Synchronized, e.g. something similar to:
stdout = new NSLogWriter ();
stdout = TextWriter.Synchronized (stdout);

Related

TCL API coverage : check if a TCL command have been called and tested exaustively in a test suite

Supposing I have a TCL API like :
namespaceXY::apiXY <value> -opt1 <value1> -opt2 <value2> -opt3 <value3>
This API is used (or maybe not) in a test suite (i.e thousands of tests).
How I can check if my API have been called + tested exhaustively (all options have been called/tested).
Many thanks
You can set an execution trace on the command. That way the signature of your command won't change. So you still get the same results if any code does info args namespaceXY::apiXY. Also error messages are not affected.
proc cmdtracer {cmd op} {
global cmdtracer
dict incr cmdtracer $cmd
}
trace add execution namespaceXY::apiXY enter cmdtracer
In the end you'll have a cmdtracer dict that contains the counts of each way the command was called. You will have to figure out yourself how to check if all options have been tested. There is not enough information in your question to provide suggestions for that part.
See #SchelteBron's answer for covering commands.
Exhaustively testing all options is going to be tricky, since they could potentially all interact in complex ways and some may be mutually-exclusive (think about the standard Tcl lsearch command for example). However, auditing that all options are at least called in your own commands can be done by additional audit-only probes. Checking all the sensible combinations of them is a manual task; you probably need a coverage tool for that.
Auditing Options in C Commands
Assuming that you're dealing with the case where you've got a C command that uses Tcl_GetIndexFromObj() to parse the option name (this is common and recommended) and where you don't mind having a threading hazard (also pretty common) the idea is simple. Make an integer variable (probably with file scope) in your C code, bind it to a Tcl variable with Tcl_LinkVar(), then use the resulting index from your (successful) Tcl_GetIndexFromObj() call to set a bit in that integer variable that says that the option was parsed.
#ifdef AUDIT_OPTIONS
static int foobar_optionTracker;
#endif
// in the implementation function, called FoobarImpl here for sake of argument
int index;
if (Tcl_GetIndexFromObj(interp, objPtr, optionNameTable, "option", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
#ifdef AUDIT_OPTIONS
foobar_optionTracker |= 1 << index;
// Theoretically should call Tcl_UpdateLinkedVar() here, but for audit-only its not important
#endif
switch (index) {
// ...
}
// In your command registration function
Tcl_CreateObjCommand(interp, "foobar", FoobarImpl, NULL, NULL);
#ifdef AUDIT_OPTIONS
Tcl_LinkVar(interp, "optionTracker(foobar)", (void*) &foobar_optionTracker, TCL_LINK_INT);
#endif
With that in place, you can just read the array element optionTracker(foobar) from your Tcl test control code to see what options have been parsed (assuming you're happy with a bit-mask) in the foobar command since the last time the mask was reset. You reset the mask by just writing 0 to it.
Note that there's also Tcl_GetIndexFromObjStruct() in the C API, but auditing coverage of that is not significantly different from above.
Auditing Options in Tcl Commands
The equivalent of Tcl_GetIndexFromObj() in pure Tcl code is tcl::prefix match, but that doesn't return an index. Instead it returns the full option name that you can use with switch. Auditing that is most easily done with a full array. (This is morally the same as what the version for the C code does, but adapted to work with the optimal tools in a particular language.)
proc foobar {mandatoryArgument1 mandatoryArgument2 args} {
# Parse other things here, set up the TABLE of option descriptors, etc.
foreach option $args {
set option [tcl::prefix match $TABLE $option]
if {$::DoAudit} {
set ::foobarAudit($option) 1
}
switch -- $option {
# etc...
}
}
You can use things like array size foobarAudit to count the number of options actually used, or parray foobarAudit to print out what was actually used.

How do I debug lua functions called from conky?

I'm trying to add some lua functionality to my existing conky setup so that repetitive "code" in my conky text can be cleaned up. For example, I have information for each mounted FS, each core, etc. where each row displayed in my panel differs ONLY by one parameter.
My first skeletal, attempt at using lua functions for this seems to run but displays nothing in my panel. I've only found very simple examples to base this on, so I may have made a simple error, but I don't even know how to diagnose it. My code here is modeled after what I HAVE been able to find regarding writing functions, such as this How to implement a basic Lua function in Conky? , but that's about all the depth I've found on the topic except for drawing and cairo examples.
Here's the code added to my conky config, as well as the contents of my functions.lua file
conky.config = {
...
lua_load = '/home/conky-manager/MyConky/functions.lua',
};
conky.text = [[
...
${voffset 5}${lua conky_test 'test'}
...
]]
file - functions.lua
function conky_test(parm1)
return 'result text'
end
What I would expect is to see is "result text" displayed in my panel at the location where that function call appears, but nothing shows.
Is there a log created by conky as it runs, or a way to provide some debug output? Even if I'd made a simple error here, I'd still like to have the ability to diagnose things as my code gets more complex.
Success!
After cobbling info from several articles together, I figured out my basic flaws -
1. Missing a 'conky_main' function,
2. Missing a 'lua_draw_hook_post' to invoke it, and
3. Realizing that if I invoke conky from a terminal, print statements in lua would appear there.
So, for anyone who sees this question and has the same issues, here's the corrected code.
conky.config = {
...
lua_load = '/home/conky-manager/MyConky/functions.lua',
lua_draw_hook_post = "main",
};
conky.text = [[
...
${lua conky_test 'test'}
...
]]
and the proper basics in my functions.lua file
function conky_test(parm1)
return 'result text'
end
function conky_main()
if conky_window == nil then
return
end
end
A few notes:
I still haven't determined if using 'lua_draw_hook_pre' instead of 'lua_draw_hook_post' makes any difference, but it doesn't seem to in this example.
Also, some examples showed actually calling this 'test' function instead of writing a 'main', but the 'main' seemed to have value in checking to see if conky_window existed.
Some examples seemed to state that naming functions with the prefix 'conky_' was required, but then showed examples of calling those functions without the prefix, so I assume the prefix is inferred during the call.
a major note: you should run conky from the directory containing the lua scripts.

Reading byte array the second time causes error?

I am using the following code to read an error message from a byte array and it works fine the first time but if I try to access it the second time it throws an error:
errorData = process.standardError.readUTFBytes(process.standardError.bytesAvailable);
StandardError is of type InboundPipe?
The error is:
Error: Error #3212: Cannot perform operation on a NativeProcess that is not running.
even though the process is running (process.running is true). It's on the second call to readUTFBytes that seems to be the cause.
Update:
Here is the code calling the same call one after another. The error happens on the next line and process.running has not changed from true. Happens on the second call.
errorData = process.standardError.readUTFBytes(process.standardError.bytesAvailable);
errorData = process.standardError.readUTFBytes(process.standardError.bytesAvailable);
I also found out the standardError is a InboundPipe instance and implements IDataInput.
Update 2:
Thanks for all the help. I found this documentation when viewing the bytesAvailable property.
[Read Only] Returns the number of bytes of data available for reading
in the input buffer. User code must call bytesAvailable to ensure that
sufficient data is available before trying to read it with one of the
read methods.
When I call readUTFBytes() it resets the bytes available to 0. So when I read it a second time and there are no bytes available it causes the error. The error is or may be incorrect in my opinion or the native process.running flag is incorrect.
I looked into seeing if it has a position property and it does not, at least not in this instance.
Could you try to set position to zero before reading process, especially before repetitive access:
Moves, or returns the current position, in bytes, of the file pointer into the ByteArray object. This is the point at which the next call to a read method starts reading or a write method starts writing.
//ByteArray example
var source: String = "Some data";
var data: ByteArray = new ByteArray();
data.writeUTFBytes(source);
data.position = 0;
trace(data.readUTFBytes(data.bytesAvailable));
data.position = 0;
trace(data.readUTFBytes(data.bytesAvailable));
This was a tricky problem since the object was not a byte array although it looks and acts like one (same methods and almost same properties). It is an InboundPipe that also implements IDataInput.
I found this documentation when viewing the bytesAvailable property.
[Read Only] Returns the number of bytes of data available for reading
in the input buffer. User code must call bytesAvailable to ensure that
sufficient data is available before trying to read it with one of the
read methods.
When I call readUTFBytes() it resets the bytes available to 0. So when I call it a second time and there are no bytes available it causes the error. The error is or may be incorrect in my opinion or the native process.running flag is incorrect although I have reason to believe it's the former.
The solution is to check bytesAvailable before calling read operations and store the value if it needs to be accessed later.
if (process.standardError.bytesAvailable) {
errorData = process.standardError.readUTFBytes(process.standardError.bytesAvailable);
errorDataArray.push(errorData);
}
I looked into seeing if it has a position property and it does not, at least not in this instance.

Lwt and database access

I can't get my database access work with lwt. Should I include it in a thread? How? Or make a new thread which returns a 'a lwt value? If so, what to do with that value?
The same goes for Printf.eprintf, which also seems to be blocked by lwt. So I use Lwt_io instead. But why would lwt block regular io?
What I have is a simple db request like Db.update session. It is within an Lwt_main.run main function. All this is within a CGI script (should not matter, database access works fine until I start with the lwt commands).
I can give you more code if needed.
Regards
Olle
Edit
let main sock env =
(* code omitted *)
Gamesession.update_game_session env#db game_session_connected;
(* code omitted *)
Lwt_main.run (main sock_listen env)
Edit 2
This was the solution:
Lwt_preemptive.detach (fun () -> Db.call) ()
Printf.eprintf is not "blocked", it's just that the buffering parameters are changed and often messages do not display before the end of the program. You should try eprintf "something\n%!" (%! means "flush"), but yes it's better to use Lwt_io.
For the database, I don't know, you did not say which library you're using (at least the one called ocaml-mysql is not Lwt-friendly, so it may require using Lwt_preemptive).
Edit
Your:
Lwt_preemptive.detach (fun () -> Db.call) ()
This call creates a thread that, once executed, returns immediately the function Db.call. So, basically in that case Lwt_preemptive.detach does nothing :)
I don't know ocaml-mysql but if:
Db.call: connection_params -> connection_handle
you would have
let lwt_db_call connection_params =
Lwt_preemptive.detach Db.call connection_params

'Invalid Handle object' when using a timer inside a function in MatLab

I am using a script in MatLab that works perfectly fine by itself, but I need to make a function out of it.
The script read a .csv file, extract all values, start a timer, and at each tick displays the corresponding coordinates extracted from the .csv, resulting in a 3D animation of my graph.
What I would like is to give it the location of the .csv, so that it starts displaying the graphs for this csv.
Here is what I have come up with:
function handFig(fileLoc)
csv=csvread(fileLoc,1,0);
both = csv(:,2:19);
ax=axes;
set(ax,'NextPlot','replacechildren');
Dt=0.1; %sampling period in secs
k=1;
hp1=text(both(k,1),both(k,2),both(k,3),'thumb'); %get handle to dot object
hold on;
hp2=text(both(k,4),both(k,5),both(k,6),'index');
hp3=text(both(k,7),both(k,8),both(k,9),'middle');
hp4=text(both(k,10),both(k,11),both(k,12),'ring');
hp5=text(both(k,13),both(k,14),both(k,15),'pinky');
hp6=text(both(k,16),both(k,17),both(k,18),'HAND');
L1=plot3([both(k,1),both(k,16)],[both(k,2),both(k,17)],[both(k,3),both(k,18)]);
L2=plot3([both(k,4),both(k,16)],[both(k,5),both(k,17)],[both(k,6),both(k,18)]);
L3=plot3([both(k,7),both(k,16)],[both(k,8),both(k,17)],[both(k,9),both(k,18)]);
L4=plot3([both(k,10),both(k,16)],[both(k,11),both(k,17)],[both(k,12),both(k,18)]);
L5=plot3([both(k,13),both(k,16)],[both(k,14),both(k,17)],[both(k,15),both(k,18)]);
hold off;
t1=timer('TimerFcn','k=doPlot(hp1,hp2,hp3,hp4,hp5,hp6,L1,L2,L3,L4,L5,both,t1,k)','Period', Dt,'ExecutionMode','fixedRate');
start(t1);
end
And the doplot function used:
function k=doPlot(hp1,hp2,hp3,hp4,hp5,hp6,L1,L2,L3,L4,L5,pos,t1,k)
k=k+1;
if k<5000%length(pos)
set(hp1,'pos',[pos(k,1),pos(k,2),pos(k,3)]);
axis([0 255 0 255 0 255]);
set(hp2,'pos',[pos(k,4),pos(k,5),pos(k,6)]);
set(hp3,'pos',[pos(k,7),pos(k,8),pos(k,9)]);
set(hp4,'pos',[pos(k,10),pos(k,11),pos(k,12)]);
set(hp5,'pos',[pos(k,13),pos(k,14),pos(k,15)]);
set(hp6,'pos',[pos(k,16),pos(k,17),pos(k,18)]);
set(L1,'XData',[pos(k,1),pos(k,16)],'YData',[pos(k,2),pos(k,17)],'ZData',[pos(k,3),pos(k,18)]);
set(L2,'XData',[pos(k,4),pos(k,16)],'YData',[pos(k,5),pos(k,17)],'ZData',[pos(k,6),pos(k,18)]);
set(L3,'XData',[pos(k,7),pos(k,16)],'YData',[pos(k,8),pos(k,17)],'ZData',[pos(k,9),pos(k,18)]);
set(L4,'XData',[pos(k,10),pos(k,16)],'YData',[pos(k,11),pos(k,17)],'ZData',[pos(k,12),pos(k,18)]);
set(L5,'XData',[pos(k,13),pos(k,16)],'YData',[pos(k,14),pos(k,17)],'ZData',[pos(k,15),pos(k,18)]);
else
k=1;
set(hp1,'pos',[pos(k,1),pos(k,2),pos(k,3)]);
axis([0 255 0 255 0 255]);
set(hp2,'pos',[pos(k,4),pos(k,5),pos(k,6)]);
set(hp3,'pos',[pos(k,7),pos(k,8),pos(k,9)]);
set(hp4,'pos',[pos(k,10),pos(k,11),pos(k,12)]);
set(hp5,'pos',[pos(k,13),pos(k,14),pos(k,15)]);
set(hp6,'pos',[pos(k,16),pos(k,17),pos(k,18)]);
end
However, when I run handFig('fileName.csv'), I obtain the same error everytime:
??? Error while evaluating TimerFcn for timer 'timer-7'
Invalid handle object.
I figured that it might come from the function trying to create a new 'csv' and 'both' everytime, so I tried removing them, and feeding the function the data directly, without results.
What is exactly the problem? Is there a solution?
Thanks a lot!
I think it's because when you call doPlot in the timer for the first time, you pass in t1 as an argument, and it might not exist the first time.
Does doPlot need t1 at all? I'd suggest modifying it so it's not used, and then your call to:
t1=timer('TimerFcn','k=doPlot(hp1,hp2,hp3,hp4,hp5,hp6,L1,L2,L3,L4,L5,both,k)','Period', Dt,'ExecutionMode','fixedRate');
Note the missing t1 in the doPlot call.
Either that, or initialise your t1 before you create the timer so it has some value to pass in.
Update (as an aside, can you use pause(Dct) in a loop instead? seems easier)
Actually, now I think it's a problem of scope.
It took a bit of digging to get to this, but looking at the Matlab documentation for function callbacks, it says:
When MATLAB evaluates function handles, the same variables are in scope as when the function handle was created. (In contrast, callbacks specified as strings are evaluated in the base workspace.)
You currently give your TimerFcn argument as a string, so k=doPlot(...) is evaluated in the base workspace. If you were to go to the matlab prompt, run handFig, and then type h1, you'd get an error because h1 is not available in the global workspace -- it's hidden inside handFig.
That's the problem you're running into.
However, the workaround is to specify your function as a function handle rather than a string (it says function handles are evaluated in the scope in which they are created, ie within handFig).
Function handles to TimerFcn have to have two arguments obj and event (see Creating Callback Functions). Also, that help file says you have to put doPlot in its own m-file to have it not evaluate in the base Matlab workspace.
In addition to these two required input arguments, your callback
function can accept application-specific arguments. To receive these
input arguments, you must use a cell array when specifying the name of
the function as the value of a callback property. For more
information, see Specifying the Value of Callback Function Properties.
It goes through an example of what you have to do to get this working. Something like:
% create timer
t = timer('Period', Dt,'ExecutionMode','fixedRate');
% attach `k` to t so it can be accessed within doPlot
set(t,'UserData',k);
% specify TimerFcn and its extra arguments:
t.TimerFcn = { #doPlot, hp1, hp2, hp3, ...., both };
start(t)
Note -- the reason k is set in UserData is because it needs to be somehow saved and modified between calls to doPlot.
Then modify your doPlot to have two arguments at the beginning (which aren't used), and not accept the k argument. To extract k you do get(timer_obj,'UserData') from within doPlot:
function k=doPlot(timer_obj, event, hp1,hp2,hp3,.....)
k = get(timer_obj,'UserData');
.... % rest of code here.
% save back k so it's changed for next time!
set(timer_obj,'UserData',k);
I think that's on the right track - play around with it. I'd highly recommend the mathworks forums for this sort of thing too, those people are whizzes.
This thread from the mathworks forum was what got me started and might prove helpful to you.
Good luck!