I'm trying to implement some fairly basic/standard Xamarin.iOS code around sharing credentials between my iOS app and associated website.
public void TryGetSharedCredential(Action<Tuple<string, string>> callback)
{
try
{
Security.SecSharedCredential.RequestSharedWebCredential("www.jg.com", "me#jg.com", (accounts, err) =>
{
if (accounts != null && accounts.Any())
{
var email = accounts[0];
var password = accounts[1];
callback(new Tuple<string, string>(email, password));
}
});
}
catch (Exception ex)
{
//log exception
}
callback(null);
}
However, RequestSharedWebCredential crashes with the following log (and never enters the NSAction).
2017-10-02 16:33:30.083 JGMobileIOS[65076:4639965] -[__NSCFDictionary UTF8String]: unrecognized selector sent to instance 0x608000282f40
2017-10-02 16:33:30.091 JGMobileIOS[65076:4639965] Xamarin.iOS: Received unhandled ObjectiveC exception: NSInvalidArgumentException -[__NSCFDictionary UTF8String]: unrecognized selector sent to instance 0x608000282f40
2017-10-02 16:33:34.363 JGMobileIOS[65076:4640005] critical: Stacktrace:
2017-10-02 16:33:34.364 JGMobileIOS[65076:4640005] critical:
Native stacktrace:
2017-10-02 16:33:34.365 JGMobileIOS[65076:4640005] critical: 0 JGMobileIOS 0x0000000104938004 mono_handle_native_crash + 244
2017-10-02 16:33:34.366 JGMobileIOS[65076:4640005] critical: 1 JGMobileIOS 0x0000000104945970 mono_sigsegv_signal_handler + 288
2017-10-02 16:33:34.366 JGMobileIOS[65076:4640005] critical: 2 libsystem_platform.dylib 0x000000011151db3a _sigtramp + 26
2017-10-02 16:33:34.366 JGMobileIOS[65076:4640005] critical: 3 ??? 0x0000000000000000 0x0 + 0
2017-10-02 16:33:34.366 JGMobileIOS[65076:4640005] critical: 4 JGMobileIOS 0x00000001049988bc mono_debug_symfile_lookup_method + 44
2017-10-02 16:33:34.366 JGMobileIOS[65076:4640005] critical: 5 JGMobileIOS 0x00000001049fc87d lookup_method_func + 61
2017-10-02 16:33:34.367 JGMobileIOS[65076:4640005] critical: 6 JGMobileIOS 0x0000000104ad75bd monoeg_g_hash_table_foreach + 77
2017-10-02 16:33:34.367 JGMobileIOS[65076:4640005] critical: 7 JGMobileIOS 0x00000001049fc2f9 mono_debug_lookup_method_async_debug_info + 105
2017-10-02 16:33:34.367 JGMobileIOS[65076:4640005] critical: 8 JGMobileIOS 0x000000010489bfbb ss_start + 331
2017-10-02 16:33:34.367 JGMobileIOS[65076:4640005] critical: 9 JGMobileIOS 0x0000000104897b16 debugger_thread + 27910
2017-10-02 16:33:34.367 JGMobileIOS[65076:4640005] critical: 10 JGMobileIOS 0x0000000104a4b283 start_wrapper + 675
2017-10-02 16:33:34.367 JGMobileIOS[65076:4640005] critical: 11 libsystem_pthread.dylib 0x000000011152f93b _pthread_body + 180
2017-10-02 16:33:34.368 JGMobileIOS[65076:4640005] critical: 12 libsystem_pthread.dylib 0x000000011152f887 _pthread_body + 0
2017-10-02 16:33:34.368 JGMobileIOS[65076:4640005] critical: 13 libsystem_pthread.dylib 0x000000011152f08d thread_start + 13
2017-10-02 16:33:34.368 JGMobileIOS[65076:4640005] critical:
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================
I have tried:
On simulator and device
Without any linking ("Don't Link")
Also tried the overloads that don't specify domain and account. According to the docs, if you pass a null domain, the domains specified in
Entitlements.plist are checked. And if you specify a null account,
then all stored accounts for that domain are supposed to be returned.
Same crash.
I have checked entitlements.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:www.jg.com</string>
<string>webcredentials:www.jg.com</string>
</array>
</dict>
</plist>
I have the correct json at: www.jg.com/.well-known/apple-app-site-association (on https)
{
"applinks": {
//applink stuff
},
"webcredentials": {
"apps": [
//full teamid + appid
]
}
}
I believe something is going wrong underneath the following Xamarin -> iOS api method mapping:
public static void AddSharedWebCredential (string domainName, string account, string password, Action<NSError> handler);
public static string CreateSharedWebCredentialPassword ();
public static void RequestSharedWebCredential (string domainName, string account, Action<string[], NSError> handler);
[Introduced (PlatformName.iOS, 8, 0, PlatformArchitecture.None, null)]
[DllImport ("/System/Library/Frameworks/Security.framework/Security")]
private static extern void SecAddSharedWebCredential (IntPtr fqdn, IntPtr account, IntPtr password, IntPtr completionHandler);
[Introduced (PlatformName.iOS, 8, 0, PlatformArchitecture.None, null)]
[DllImport ("/System/Library/Frameworks/Security.framework/Security")]
private static extern IntPtr SecCreateSharedWebCredentialPassword ();
[Introduced (PlatformName.iOS, 8, 0, PlatformArchitecture.None, null)]
[DllImport ("/System/Library/Frameworks/Security.framework/Security")]
private static extern void SecRequestSharedWebCredential (IntPtr fqdn, IntPtr account, IntPtr completionHandler);
How can I get more details on what is going wrong? Am I missing anything and/or what else can I try?
After working with a Xamarin Support Engineer, turns out this was a bug in Xamarin.iOS, and will be fixed in a future release:
https://bugzilla.xamarin.com/show_bug.cgi?id=60423
Fix committed here: https://github.com/xamarin/xamarin-macios/commit/03b9d1759e0bafe5d94d319e5a58f798a3ce575b
Related
Recently, I am running into trouble of calling popen, it seems to be not thread safe.
The following is the code snippet from the source code link: http://androidxref.com/9.0.0_r3/xref/bionic/libc/upstream-netbsd/lib/libc/gen/popen.c
static struct pid {
struct pid *next;
FILE *fp;
int fd;
pid_t pid;
} *pidlist;
static rwlock_t pidlist_lock = RWLOCK_INITIALIZER;
FILE *
popen(const char *command, const char *type)
{
struct pid *cur, *old;
...
pipe2(pdes, flags) // A
...
(void)rwlock_rdlock(&pidlist_lock); // C
...
switch (pid = vfork()) { // C.1
case 0: /* Child. */
...
_exit(127);
/* NOTREACHED */
}
/* Parent; */
...
/* Link into list of file descriptors. */
cur->fp = iop;
cur->pid = pid;
cur->next = pidlist; // D
pidlist = cur; // E
(void)rwlock_unlock(&pidlist_lock); // F
...
}
Observing the above code, it acquired a read-lock at C, but, inside the scope, it did some write operations at E. So, there will be possibly multiple read threads who are writing to the variable "pidlist" in the same time.
Does anyone know whether it is a true issue or not?
Looking at the code, it is not how you outline it.
Here is a paste from the given link http://androidxref.com/9.0.0_r3/xref/bionic/libc/upstream-netbsd/lib/libc/gen/popen.c
80FILE *
81popen(const char *command, const char *type)
82{
83 struct pid *cur, *old;
94 if (strchr(xtype, '+')) {
...
100 } else {
103 if (pipe2(pdes, flags) == -1)
104 return NULL;
105 }
106
...
113
114 (void)rwlock_rdlock(&pidlist_lock);
115 (void)__readlockenv();
116 switch (pid = vfork()) {
117 case -1: /* Error. */
...
127 case 0: /* Child. */
...
154 execl(_PATH_BSHELL, "sh", "-c", command, NULL);
155 _exit(127);
156 /* NOTREACHED */
157 }
158 (void)__unlockenv();
159
160 /* Parent; assume fdopen can't fail. */
161 if (*xtype == 'r') {
...
167 } else {
...
173 }
...
179 pidlist = cur;
180 (void)rwlock_unlock(&pidlist_lock);
181
182 return (iop);
183}
It is
do the file stuff (pipe2() or socketpair())
acquire the lock (this will avoid the child doing silly things)
vfork()
on the child, reorganize filedes and execl
on parent do some filedes stuff unlock and return
I do not see what would be the problem.
I have a memory leak with this piece of code and I don't understand why.
Each thread calls the function exec. The function exec simply creates a std::vector and than delete it. This vector has length equal to the number of threads and it is created, and deleted, only once.
You can suppose that this code is thread-safe in the sense that the vector is deleted only after the creation.
class Foo{
public:
Foo(const std::size_t& numThreads):size_(numThreads){}
inline void alloc(){std::call_once(bufferflag_,&Foo::alloc_,this);}
inline void free(){std::call_once(bufferflag_,&Foo::free_,this);}
private:
const std::size_t size_;
std::vector<double>* bufferptr_;
std::once_flag bufferflag_;
inline void alloc_(){bufferptr_ = new std::vector<double>(size_);}
inline void free_(){delete [] bufferptr_;}
};
void exec(Foo& comm){
comm.alloc();
// sync the threads here with some barrier
comm.free();
}
void main(){
Foo comm(10);
std::vector<std::thread> t(10);
for(std::size_t tid=0;tid!=10;++tid) t[tid]=std::thread(exec,std::ref(comm));
for(std::size_t tid=0;tid!=10;++tid) t[tid].join();
}
HEAP SUMMARY:
in use at exit: 104 bytes in 2 blocks
total heap usage: 23 allocs, 21 frees, 3,704 bytes allocated
104 (24 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
LEAK SUMMARY:
definitely lost: 24 bytes in 1 blocks
indirectly lost: 80 bytes in 1 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 0 bytes in 0 blocks
suppressed: 0 bytes in 0 blocks
UPDATE
If instead of using call_once I just call the new and delete from the same thread, there are no memory leaks.
Take a look at this modified code:
class Foo
{
public:
Foo(const std::size_t& numThreads) :size_(numThreads) {}
inline void alloc()
{
printf("alloc\n");
std::call_once(alloc_flag, &Foo::alloc_, this);
}
inline void foo_free()
{
printf("free\n");
std::call_once(free_flag, &Foo::free_, this); // Changed from bufferflag
}
private:
const std::size_t size_;
std::vector<double>* bufferptr_;
std::once_flag alloc_flag;
std::once_flag free_flag;
inline void alloc_()
{
printf("once_alloc_!\n");
bufferptr_ = new std::vector<double>(size_);
}
inline void free_()
{
printf("once_free_!\n");
bufferptr_->clear();
delete bufferptr_; // Not delete[] bufferptr_
bufferptr_ = NULL;
}
};
void exec(Foo& comm){
comm.alloc();
// Barrier
comm.foo_free();
}
If you use 2 different once_flag for alloc and free, you run also the free_() method. The fact that you are using only one flag generates a memory leak because the flag is consumed by the first alloc.
To check memory leaks I use _CrtDumpMemoryLeaks(); and I get some extra leaks even if I comment out the thread create/join routines but I think this std::vector thrash. Hope this helps!
I am trying to hunt a bug that cause intermittent crash at PC around get_next_timer_interrupt() code and sometimes at run_timer_softirq()
I found a driver that potentially calls init_timer() often with the same static argument passed to it. (timer_list)
Will this cause issue?
What exactly does init_timer do and is there a function that does the reverse to destroy it?
Thanks
Calling init_timer() a lot should not cause any problem. The code which is eventually invoked is:
621 static void do_init_timer(struct timer_list *timer, unsigned int flags,
622 const char *name, struct lock_class_key *key)
623 {
624 struct tvec_base *base = __raw_get_cpu_var(tvec_bases);
625
626 timer->entry.next = NULL;
627 timer->base = (void *)((unsigned long)base | flags);
628 timer->slack = -1;
629 #ifdef CONFIG_TIMER_STATS
630 timer->start_site = NULL;
631 timer->start_pid = -1;
632 memset(timer->start_comm, 0, TASK_COMM_LEN);
633 #endif
634 lockdep_init_map(&timer->lockdep_map, name, key, 0);
635 }
That gets invoked by a few macros calling down to it. Start here to follow the flow.
I'm trying to throw an exception within a thread and allow the calling process to catch it. However, it seems that this will cause the entire application to crash. See test code attached never prints either exit statement.
1 #include <boost/thread.hpp>
2 #include <iostream>
3
4 void wait(int seconds)
5 {
6 boost::this_thread::sleep(boost::posix_time::seconds(seconds));
7 }
8
9 void thread()
10 {
11 for (int i = 0; i < 5; ++i)
12 {
13 wait(1);
14 std::cout << i << std::endl;
15 }
16 throw;
17 }
18
19 int main()
20 {
21 try
22 {
23 boost::thread t(thread);
24 t.join();
25 std::cout << "Exit normally\n";
26 }
27 catch (...)
28 {
29 std::cout << "Caught Exception\n";
30 }
31 }
Have a look at boost exception: Transporting of Exceptions Between Threads.
This approach has worked well for me.
I have a problem using multiple UIBarButtonItems within a UIToolbar on one side of a UINavigationController. I‘ve used one of the many examples on how to put multiple buttons in the navigation bar (using a toolbar), and while I got it displaying correctly now, I always get an unkown Objective-C exception thrown when a button is pressed.
This is the full test UIViewController I use for adding multiple buttons:
using System;
using System.Drawing;
using MonoTouch.UIKit;
namespace TestProject
{
public class Test : UIViewController
{
public override void ViewDidLoad ()
{
base.ViewDidLoad();
UIBarButtonItem btn1 = new UIBarButtonItem( "foo", UIBarButtonItemStyle.Bordered, delegate(object sender, EventArgs e) {
Console.WriteLine( "asdf" );
} );
UIBarButtonItem btn2 = new UIBarButtonItem();
btn2.Style = UIBarButtonItemStyle.Bordered;
btn2.Title = "bar";
btn2.Clicked += delegate(object sender, EventArgs e) {
Console.WriteLine( "fdsa" );
};
UIToolbar tb = new UIToolbar( new RectangleF( 0, 0, 150, 44.0f ) );
tb.SetItems( new UIBarButtonItem[] { btn1, btn2 }, false );
NavigationItem.RightBarButtonItem = new UIBarButtonItem( tb );
}
}
}
I put that controller within a UINavigationController and display its view as the only window content. Everything works fine, until I click one of the buttons:
Error connecting stdout and stderr (127.0.0.1:10001)
Stacktrace:
at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <IL 0x0009f, 0xffffffff>
at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x00038] in /Developer/MonoTouch/Source/monotouch/monotouch/UIKit/UIApplication.cs:26
at TestProject.Application.Main (string[]) [0x00000] in /Users/Apple/Projects/TestProject/TestProject/Main.cs:16
at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>
Native stacktrace:
0 TestProject 0x000d0de8 mono_handle_native_sigsegv + 343
1 TestProject 0x0000f74c mono_sigsegv_signal_handler + 322
2 libSystem.B.dylib 0x906fc45b _sigtramp + 43
3 ??? 0xffffffff 0x0 + 4294967295
4 UIKit 0x01ee6cc3 -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 156
5 UIKit 0x01cd44fd -[UIApplication sendAction:to:from:forEvent:] + 119
6 UIKit 0x01d64799 -[UIControl sendAction:to:forEvent:] + 67
7 UIKit 0x01d66c2b -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
8 UIKit 0x01d657d8 -[UIControl touchesEnded:withEvent:] + 458
9 UIKit 0x01cf8ded -[UIWindow _sendTouchesForEvent:] + 567
10 UIKit 0x01cd9c37 -[UIApplication sendEvent:] + 447
11 UIKit 0x01cdef2e _UIApplicationHandleEvent + 7576
12 GraphicsServices 0x0404f992 PurpleEventCallback + 1550
13 CoreFoundation 0x00ea2944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
14 CoreFoundation 0x00e02cf7 __CFRunLoopDoSource1 + 215
15 CoreFoundation 0x00dfff83 __CFRunLoopRun + 979
16 CoreFoundation 0x00dff840 CFRunLoopRunSpecific + 208
17 CoreFoundation 0x00dff761 CFRunLoopRunInMode + 97
18 GraphicsServices 0x0404e1c4 GSEventRunModal + 217
19 GraphicsServices 0x0404e289 GSEventRun + 115
20 UIKit 0x01ce2c93 UIApplicationMain + 1160
21 ??? 0x077efe64 0x0 + 125763172
22 ??? 0x077ef1e2 0x0 + 125759970
23 ??? 0x077ef0be 0x0 + 125759678
24 ??? 0x077ef145 0x0 + 125759813
25 TestProject 0x0000f507 mono_jit_runtime_invoke + 1332
26 TestProject 0x001ed259 mono_runtime_invoke + 137
27 TestProject 0x001ef940 mono_runtime_exec_main + 669
28 TestProject 0x001eed2a mono_runtime_run_main + 843
29 TestProject 0x000a3093 mono_jit_exec + 200
30 TestProject 0x002a163d main + 4060
31 TestProject 0x00002819 _start + 208
32 TestProject 0x00002748 start + 40
Debug info from gdb:
dyld: could not load inserted library: /Users/Apple/Library/Application Support/iPhone Simulator/4.3/Applications/86C48AC1-821F-49DD-B344-58471F02D31B/TestProject.app/monotouch-fixes.dylib
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================
Does anyone know what‘s causing this, and more importantly how to avoid it? When setting just a single button as the RightBarButtonItem it works without any problems.
edit
Above error seems to randomly cycle with this one:
Error connecting stdout and stderr (127.0.0.1:10001)
2011-08-25 13:30:05.409 TestProject[1235:a0b] -[__NSCFSet InvokeAction:]: unrecognized selector sent to instance 0x7168980
Unhandled Exception: MonoTouch.Foundation.MonoTouchException: Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[__NSCFSet InvokeAction:]: unrecognized selector sent to instance 0x7168980
at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Developer/MonoTouch/Source/monotouch/monotouch/UIKit/UIApplication.cs:26
at TestProject.Application.Main (System.String[] args) [0x00000] in /Users/Apple/Projects/TestProject/TestProject/Main.cs:16
[ERROR] FATAL UNHANDLED EXCEPTION: MonoTouch.Foundation.MonoTouchException: Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[__NSCFSet InvokeAction:]: unrecognized selector sent to instance 0x7168980
at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Developer/MonoTouch/Source/monotouch/monotouch/UIKit/UIApplication.cs:26
at TestProject.Application.Main (System.String[] args) [0x00000] in /Users/Apple/Projects/TestProject/TestProject/Main.cs:16
Declare the buttons as class variables. The GC collects them so your event handlers are causing memory leaks.