http://bugzilla.novell.com/show_bug.cgi?id=623114
http://bugzilla.novell.com/show_bug.cgi?id=623114#c0 Summary: MonoTouch App Fails on the iPhone with illogical stack trace and works on the Simulator Classification: Mono Product: MonoTouch Version: unspecified Platform: Other OS/Version: Mac OS X 10.6 Status: NEW Severity: Critical Priority: P5 - None Component: Runtime AssignedTo: [email protected] ReportedBy: [email protected] QAContact: [email protected] Found By: Development Blocker: --- Description of Problem: An application that communicates over the web, uses encryption and saves/reads local files with encrypted text blobs, is failing to write to the files, while running in the device, aborting with some exceptions on stack frames that couldn't possibly be being called. It works normally on the iPhone Simulator. Adding code to help debug (as we can't make the soft debugger to work over the firewall between our wifi network and our hardwired development network) sometimes changes the place the exception occurs in unpredictable ways >From the symptoms it looks like native code generation is doing something wrong with the circularly constrained hierarchy of of generics-based classes. See below Steps to reproduce the problem: 1. Compile App for Simulator 2. Deploy to simulator 3. Runs, fill in the needed info, expects download, results oK 4. Compile App for iPhone 5. Deploy to iPhone 3G, running iOS 4.0 6. Runs, fill in the needed info, expects download, fail to save and complete the process Actual Results: It breaks on a call to something that is not being called. So it stops the process of saving the downloaded information. Expected Results: To simply write the received data an go on. How often does this happen? Currently always, even if the app is completely uninstalled first. Additional Information: The circularly constrained code is (partial): namespace OpenCS.MTrusted.iPhone.Core.Storage { public class Account : SerializableAsText<Account> { public Account () { } public override string UniqueName { get { return Name.Replace(" ", ""); } } public override string AsText { get { return Name + '\n' + SerializedToken; } set { string[] parts = value.Split('\n'); Name = parts[0]; SerializedToken = parts[1]; } } public string Name { get; set; } public int EnterpriseId { get; set; } public string SerializedToken { get; set; } } public class Enterprise : SerializableAsText<Enterprise, Account> { .. } public abstract class SerializableAsText { public abstract string UniqueName { get; } public abstract string AsText { get; set; } public virtual SerializableAsText Parent { get; set; } public abstract void Save (); public abstract void Delete (); internal bool Modified { get; set; } internal bool Deleted { get; set; } internal IPersister Persister { get; set; } protected SerializableAsText() { Deleted = false; } public override bool Equals (object obj) { SerializableAsText other = obj as SerializableAsText; return other != null && other.UniqueName == UniqueName && other.AsText == AsText; } public override int GetHashCode () { return UniqueName.GetHashCode (); } } public abstract class SerializableAsText<T> : SerializableAsText where T : SerializableAsText, new() { private const string DeletedPrefix = "Deleted-"; public override void Save () { Console.WriteLine("Saving " + FullPath); using (StreamWriter sw = new StreamWriter (FullPath, false, Encoding.UTF8)) { if (Deleted) sw.Write(DeletedPrefix); sw.WriteLine(AsText); sw.Close(); Persister.Register(FileName); } Modified = false; } public override void Delete () { Deleted = true; Save(); } protected internal static T Load (string path, IPersister persister) { Console.WriteLine("Loading " + path); using (StreamReader sr = new StreamReader(path, Encoding.UTF8)) { string serializedValue = sr.ReadToEnd(); T it = new T(); it.Persister = persister; if (serializedValue.StartsWith(DeletedPrefix)) { it.Deleted = true; serializedValue = serializedValue.Substring(DeletedPrefix.Length); } it.AsText = serializedValue; it.Modified = false; sr.Close(); return it; } } private static string FileMask (SerializableAsText parent) { return Compose(parent, "*", typeof(T).Name.ToLowerInvariant()); } public static IList<T> List (SerializableAsText parent, IPersister persister) { List<T> entities = new List<T>(); foreach (string path in persister.GetPaths(parent, FileMask (parent))) { try { T entity = Load(path, persister); if (!entity.Deleted) { entity.Parent = parent; entities.Add(entity); } } catch (Exception e) { Console.WriteLine("Error while loading data from '{0}': {1}", path, e); } } return entities; } internal string FullPath { get { return Persister.FullPath(FileName); } } private string FileName { get { return Compose(Parent, UniqueName, Extension); } } protected static string Extension { get { return typeof(T).Name.ToLowerInvariant(); } } protected static string Compose (SerializableAsText parent, string middle, string extension) { if (parent == null) return middle + "." + extension; return parent.UniqueName + "." + middle + "." + extension; } } public abstract class SerializableAsText<T, C> : SerializableAsText<T> where T : SerializableAsText<T, C>, new() where C : SerializableAsText<C>, new() { public abstract IList<C> Children { get; set; } public override void Delete () { base.Delete(); if (Children != null) foreach (SerializableAsText child in Children) child.Delete(); } public static IList<T> ListAll (IPersister persister) { IList<T> entities = SerializableAsText<T>.List(null, persister); foreach (T entity in entities) entity.Children = SerializableAsText<C>.List(entity, persister); return entities; } } } It fails when calling the Save() method on Enterprise (inherited from SerializableAsText<T,C>), which doesn't appear in the Stack Trace but is the only real candidate as the last meaningful frame in the stack trace is on this method on another class (called the StorageManager) public void SaveEnterprise (Enterprise e) { if (e == null) { throw new ArgumentNullException(); } e.Persister = persister; e.Save(); } I`ll try to hand copy below the stack trace I have put in an AlertView in the iPhone, that I can't debug by network difficulties as I've stated before. System.IndexOutOfRangeException: Array index is out of range at OpenCS.MTrusted.iPhone.Core.Crypto.PBEGenerator.UpdateCounter(Int32 round) ... at OpenCS.MTrusted.iPhone.Core.Crypto.PBEGenerator.PBKDF2(System.Byte[] salt, Int32 round) ... at OpenCS.MTrusted.iPhone.Core.Storage.StorageManager.SaveEnterprise(OpenCS.MTrusted.iPhone.Core.Storage.Enterprise e) ... Another important detail: These classes are built into a library project (OpenCS.MTrusted.iPhone.Core) referenced from the MonoTouch iPhone Application project (OpenCS.MTrusted.iPhone) -- Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the QA contact for the bug. You are the assignee for the bug. _______________________________________________ mono-bugs maillist - [email protected] http://lists.ximian.com/mailman/listinfo/mono-bugs
