Xamarin.Mac NSThread.Start() stack overflow - c#

I've got a rather complex Xamarin.Mac application. In fact, it's a windows forms application, but we're using Mono for Mac compatibility with a native Mac GUI. One of our business logic components involves watching the filesystem for changes using FSWatcher. Unfortunately, FSWatcher on Mac is horribly broken, leaving us to use the native FSEvents API via Xamarin.Mac.
Deep down in business logic, I've got a custom class called CBFileSystemWatcher which wraps the .NET FSWatcher, and on mac provides an adapter between the FSWatcher-expecting business logic and FSEvents on mac. INSIDE this compatibility class, I've got
private FSEventStream eventStream;
//...
this.eventStream.ScheduleWithRunLoop (NSRunLoop.Main);
which schedules the filesystem events on the main run loop. Unfortunately, this means the GUI blocks FS event handling, so suddenly if a modal dialog is open, for example, fs events stop getting processed.
My thought is to create a new runloop for the FS event scheduling, which I figure looks like
NSThread.Start(()=>{
// Some other code
this.eventStream.ScheduleWithRunLoop (NSRunLoop.Current);
});
The snag is, I think, that this code runs inside maybe two other layers of thread starts. For testing purposes, I've got the following code where I NEED the above code:
NSThread.Start(()=>{
int i = 0;
});
with a breakpoint on the middle line to determine whether it was hit. 9 times out of ten I get the following stack overflow:
Stack overflow in unmanaged: IP: 0x261ba35, fault addr: 0xb02174d0
Stack overflow in unmanaged: IP: 0x261ba35, fault addr: 0xb02174d0
(the addresses change, though often recur)
One time out of ten the code works exactly as expected and I break on i=0
To test this further, I placed the above test inside my main AppDelegate.cs FinishedLaunching method. There, the code reliably works.
To further confuse matters, I placed the following code at the start of FinishedLaunching:
var fooThread = new Thread(() =>
{
var barThread = new Thread(()=>{
NSThread.Start(() =>
{
int i = 4;
});
});
barThread.Start();
});
fooThread.Start();
With breakpoints on fooThread.Start();, barThread.Start();, and int i = 4; the code works exactly as expected, where the points are hit in reverse order.
My question is, does anyone have any ideas on how to even begin deubgging this? The SO is so out of the blue I don't even know where to start.

A year later, I have this answer for you:
http://forums.xamarin.com/discussion/37451/more-modal-problems-nsmenu-nsstatusitem

Related

App.MobileService.LoginAsync fails to show dialog on select machine -> Mind Blown

Just wondering if anyone might be able to point me in the right direction here.
user = await App.MobileService.LoginAsync(provider)
this is the line of code in question. The problem is; this works fine on 2/3 test machines (All Windows 10), the dialog is displayed and the program operates as expected. on the third machine however, the dialog does not display. I have wrapped the function in a try catch block and I am catching all exceptions that I then route to a MessageDialog to display on the screen. the messages are never shown, as though the try succeeded, but the function exits on that line exactly and throws no exceptions. I am using MobileServiceAuthenticationProvider.MicrosoftAccount as my provider.
Code redacted to highlight the error, the full code returns a boolean value for success/failure. All traces past the failing line do not appear, so the function is definitely exiting at the specified line.
try
{
//This line fails on a single machine out of three
user = await App.MobileService.LoginAsync(provider)
}
catch(Exception e)
{
//when it fails, this does not trigger, and no traces after this point
//appear until outside the function
MessageDialog msg = new MessageDialog(e.ToString());
await msg.ShowAsync();
}
and just to make things really weird...message dialogs prior to this point in the code work just fine...
I suspect that the security of the machine in question is blocking the login (windows defender), but I really have no idea where to look for this, or even how to test the problem further. Any ideas as to what would prevent this single machine from displaying the Microsoft login window, or ideas on further debugging would be appreciated.
You are not awaiting the response from the Async reply. This means that you will have an ordering and concurrency issue - sometimes it will work, and sometimes it won't and it's all in the timing.
You need:
var user = await client.LoginAsync(provider);

Coded ui Test fails at random times on server

I am fairly new to the testing environment but I am stuck with a problem.
i have created a test case (a few tests combined in an ordered test) and when I run them on my own pc they always pass (tried it many times to be sure) but when I run the test on our server the test fails at random times.
examples - he doesn't right click a list to get the context menu
- he seems to forget to click on a button so he cant access the next window. etc
if i run the test again he may go over the previous fail but fails on something else.
so far. out of +- 30 times i have run he test i had 5 success runs. and this should be a base test so there should be no bug or known problem.
i have the feeling that the server needs more time to complete the test. so i did research and already added many playbacksettings and a Playback_PlaybackError.
test case made in Visual studio 2013 part with recording part written code. build in visual studio and server tested with microsoft test manager 2013, win8 envir
is there anything i do wrong? or is there something wrong with the server configuration?
Thanks in advance.
so far I tried some of these (and repeat in every testmethod)
public CodedUITest1()
{
Playback.PlaybackSettings.MatchExactHierarchy = true;
Playback.PlaybackSettings.SmartMatchOptions = SmartMatchOptions.Control;
Playback.PlaybackSettings.SmartMatchOptions = SmartMatchOptions.TopLevelWindow;
Playback.PlaybackSettings.SmartMatchOptions = SmartMatchOptions.None;
Playback.PlaybackSettings.SearchTimeout = 2000;
Playback.PlaybackSettings.ShouldSearchFailFast = true;
Playback.PlaybackSettings.ThinkTimeMultiplier = 2;
Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.AllThreads;
Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.UIThreadOnly;
Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.Disabled;
Playback.PlaybackSettings.WaitForReadyTimeout = 2000;
Playback.PlaybackError -= Playback_PlaybackError;
Playback.PlaybackError += Playback_PlaybackError;
}
/// <summary> PlaybackError event handler. </summary>
private static void Playback_PlaybackError(object sender, PlaybackErrorEventArgs e)
{
// Wait a second
System.Threading.Thread.Sleep(1000);
// Retry the failed test operation
e.Result = PlaybackErrorOptions.Retry;
}
Try to use
yourcontrol.WaitForControlReady()
function as well before performing any action on control. This function will stop the thread till your control becomes ready for accepting any action.
Seems the problem was server based. I added a global delaybetweenactions and the test seems to run very smooth. Problem fixed
I had the similar problem with a set of 20 odd Coded UI Tests in my project, which used to randomly fail on the server, but always ran fine locally. We looked out for a number of troubleshooting techniques to overcome this mysterious 'random' factor. The biggest problem while analyzing these test failures is that the error stack trace might indicate the line of code which might be completely unrelated to the actual cause of failure.
We figured out that we can enable HTML logging in our Coded UI tests. This is very easy and can either be enabled for individual tests or for all the tests in the project. Just add the below code to your app.config file
Once you have the tracing enabled, the tests will display step by step details of how Coded UI tried to execute the tests - with screenshots of your application. This is very beneficial in troubleshooting the actual cause of test failures.

CPU is 100% at multithreading

First I've read all the posts here regarding this issue and I manged to progress a bit. However it seems I do need your help :)
I have a program with several threads, sometimes (not always) the CPU usage of the program is increasing up to 100% and never reduced until I shut down the program.
As I read in other similar posts, I ran the app using the visual studio (2012 - Ultimate).
I paused the app, and open the threads window.
There I pauses the threads until I've found the 4 threads which stuck the app.
The all refer to the same line of code (a call for constructor).
I checked the constructor inside and outside and couldn't find any loop which could cause it.
To be more careful I've added break point to almost every line of code and resume the app. None of them have been triggered.
This is the line of code:
public static void GenerateDefacementSensors(ICrawlerManager cm)
{
m_SensorsMap = new Dictionary<DefacementSensorType, DefacementSensor>();
// Create instance of all sensors
// For any new defacement sensor, don't forget to add an appropriate line here
// m_SensorsMap.add(DefacementSensorType.[Type], new [Type]Sensor())
try
{
if (m_SensorsMap.Count <= 0)
{
m_SensorsMap.Add(DefacementSensorType.BackgroundSensor, new BackgroundSensor());
m_SensorsMap.Add(DefacementSensorType.TaglinesSensor, new TaglinesSensor(cm.Database));
m_SensorsMap.Add(DefacementSensorType.SingleImageSensor, new SingleImageSensor());
}
}
catch (Exception)
{
Console.WriteLine("There was a problem initializing defacement sensors");
}
}
The second "m_SensorsMap.Add" is marked with green arrow, as I understand it, it means it's still waiting to the first line to finish.
By the way, the m_SensorsMap.Count value is 3.
How can I find the problem?
Is it a loop?
Or maybe a deadlock (not make sense because it shouldn't be 100% cpu, right?)
It's pointless to upload a code because this is a huge project.
I need more general help like how to debug?
Is it could something else than a loop?
Because it's a bug that returns every while and than I'm not closing the app until I found the problem :)
Thanks in advance!!
Edit:
The constructors:
public TaglinesSensor(IDatabase db)
{
m_DB = db;
}
I couldn't found the problem so I've changed the design on order not to call those constructors anymore.
Thanks for the guys who tried to help.
Shaul

How could the existence of pseudo debug strings cause a difference in functionality?

If I have these sprinkled throughout my code:
MessageBox.Show("See a format exception yet? #1");//todo: remove
(there are 7 of these, numbered from 1..7, most of which display (1,2,5,6,7))
I end up with one err msg ("Exception: Cannot find table 0 Location: frmFunction.SetPlatypus")
If I comment out all of those, I end up with a different err msg ("Exception: FormatException Location frmFunction.getDuckbillRecord")
How could this be? Shouldn't the existence/display of such an information msg have no effect on the way the code executes/the path it takes, etc.?
Note: getDuckbillRecord() is where all of the MessageBoxes are.
UPDATE
Using RT's suggestions as motivation, I came up with this:
public static StringBuilder LogMsgs = new StringBuilder();
public static void ExceptionHandler(Exception ex, string location)
{
try
{
LogMsgs.Append(string.Format("{0}\r\n", ex.Message)); //TODO: Comment out before deploying?
DateTime dt = DateTime.Now;
string timeAsStr = string.Format("{0}_{1}_{2}_{3}.txt", dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
using (StreamWriter file = new StreamWriter(timeAsStr))
{
file.WriteLine(LogMsgs.ToString());
}
. . .
//in the problematic code, replacing the MessageBox.Show() calls:
TTBT.LogMsgs.Append("Made it to location 1 in frmOverFunction.GetDuckbillRecord()\r\n");
...and it did help - the exception is reached right after the first of 7 "code waypoints," so there's something rotten in that particular Denmark, apparently.
UPDATE 2
After the rare experience of being able to run the app without crashing somewhere, I realized I also need that file-writing code in the main form's OnClosing() event - being in the global exception handler had worked for awhile - I wasn't expecting a clean termination of the app to ever occur again, I guess.
I'd strongly encourage you NOT to use MessageBox.Show(...) to log/trace/debug errors, because popping-up a dialog can introduce many subtle bugs and changes in behavior, focus, etc., especially if your UI flow/state is important.
Instead, use System.Diagnostics.Trace for writing tracing code (which you can optionally compile into your production/release code) or System.Diagnostics.Debug to write debug messages which get removed when you build your release version.
For example:
public void DoSomething(int a, int b)
{
Trace.TraceInformation("Starting to do something: a = {0}, b = {1}",
a, b);
try
{
int c = a / b;
}
catch (DivideByZeroException e)
{
Debug.WriteLine("OH NO ... 'b' WAS ZERO!!!! RUN AWAY!!!!");
throw e;
}
Trace.TraceInformation("Done doing something");
}
In the example above, the debug output will be available in debug builds, but will be removed in release builds. Trace output will be available in debug and retail bugs (unless you turn off the TRACE build parameter) but introduces no measurable perf impact unless you hook-up a listener and start writing trace output to a slow medium like spinning disks, ticker-tape printers, etc. ;)
When you run code with Trace and/or Debug builds with Debug messages in Visual Studio, the messages are written to the Output pane so you can watch what's going on inside your app as it runs.
If you want to, you can also write a stand-alone trace listener that listens for Trace and/or Debug messages and log them to a file/database or display them in a console window (or GUI if you want to get fancy).
You can also use tools like log4net which enables you to write log/trace messages to a variety of file formats, databases, etc.

Using a SSH library to connect to unix and tail a file: Is this the right approach?

As Ive stated with a few other questions, Ive been using a new SSH .NET library to connect to a Unix server and run various scripts and commands. Well, I've finally attempted to use it to run a Unix tail -f on a live log file and display the tail in a Winforms RichTextBox.
Since the library is not fully-fleshed out, the only kinda-sorta solution I've come up with seems lacking... like the feeling you get when you know there has to be a better way. I have the connection/tailing code in a separate thread as to avoid UI thread lock-ups. This thread supports cancellation request (which will allow the connection to gracefully exit, the only way to ensure the process Unix side is killed). Here's my code thus far (which for the record seems to work, I would just like some thoughts on if this is the right way to go about it):
PasswordConnectionInfo connectionInfo = new PasswordConnectionInfo(lineIP, userName, password);
string command = "cd /logs; tail -f " + BuildFileName() + " \r\n";
using (var ssh = new SshClient(connectionInfo))
{
ssh.Connect();
var output = new MemoryStream();
var shell = ssh.CreateShell(Encoding.ASCII, command, output, output);
shell.Start();
long positionLastWrite = 0;
while (!TestBackgroundWorker.CancellationPending) //checks for cancel request
{
output.Position = positionLastWrite;
var result = new StreamReader(output, Encoding.ASCII).ReadToEnd();
positionLastWrite = output.Position;
UpdateTextBox(result);
Thread.Sleep(1000);
}
shell.Stop();
e.Cancel = true;
}
The UpdateTextBox() function is a thread-safe way of updating the RichTextBox used to display the tail from a different thread. The positionLastWrite stuff is an attempt to make sure I don’t loose any data in between the Thread.Sleep(1000).
Now Im not sure about 2 things, first being that I have the feeling I might be missing out on some data each time with the whole changing MemoryStream position thing (due to my lack of experiance with MemoryStreams, and the second being that the whole sleep for 1 second then update again thing seems pretty archaic and inefficient... any thoughts?
Mh, I just realized that you are not the creator of the SSH library (although it's on codeplex so you could submit patches), anyway: You might want to wrap your loop into a try {} finally {} and call shell.Stop() in the finally block to make sure it is always cleaned up.
Depending on the available interfaces polling might be the only way to go and it is not inherently bad. Whether or not you loose data depends on what the shell object is doing for buffering: Does it buffer all output in memory, does it throw away some output after a certain time?
My original points still stand:
One thing which comes to mind is that it looks like the shell object is buffering the whole output in memory all the time which poses a potential resource problem (out of memory). One option of changing the interface is to use something like a BlockingQueue in the shell object. The shell is then enqueuing the output from the remote host in there and in your client you can just sit there and dequeue which will block if nothing is there to read.
Also: I would consider making the shell object (whatever type CreateShell returns) IDisposable. From your description it sounds shell.Stop() is required to clean up which won't happen in case some exception is thrown in the while loop.

Categories

Resources