{"id":293,"date":"2012-06-25T22:44:48","date_gmt":"2012-06-26T03:44:48","guid":{"rendered":"http:\/\/www.compdigitec.com\/labs\/?p=293"},"modified":"2012-06-27T11:34:43","modified_gmt":"2012-06-27T16:34:43","slug":"fclose-freezes-when-run-inside-pthread-on-android-2-1","status":"publish","type":"post","link":"http:\/\/www.compdigitec.com\/labs\/2012\/06\/25\/fclose-freezes-when-run-inside-pthread-on-android-2-1\/","title":{"rendered":"fclose() freezes\/hangs when run inside pthread on Android 2.1"},"content":{"rendered":"<p>There appears to be an obscure bug that has somehow recently activated <s>on ARMv6, non-FPU builds<\/s> of VLC for Android. This has been only observed on Android 2.1 and <s>possibly on other Android 2.x platforms with ARMv6, non-FPU builds<\/s> Android 2.2. On the other hand, it works perfectly on an Android 4.0 on a NEON device (same code), so it is probably specific to Android 2.2 and 2.1 (not tested on 1.6).<\/p>\n<p>The obscure bug involves hanging during a fclose() call whilst being run inside a POSIX pthread_once thread. This obscure bug was causing hanging on startup of VLC for Android on an <a href=\"http:\/\/www.compdigitec.com\/labs\/2012\/02\/01\/android-codec-benchmarks\/\">Android 2.1, no-FPU, no-NEON device<\/a>. Further testing with the Android emulator also revealed that the <strong>Android 2.1 and 2.2 emulator<\/strong> crashes too, suggesting a bionic bug (Android 2.3 works fine). Here is a condensed, VLC-neutral version of the code from VLC core that is specific to this problem, adapted from <a href=\"http:\/\/git.videolan.org\/?p=vlc.git;a=blob;f=src\/posix\/linux_cpu.c;h=d24342457277b20d4c4efc0c02eb6e1a63e7d75a;hb=HEAD#l45\">src\/posix\/linux_cpu.c<\/a>:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/ arm-linux-androideabi-gcc --sysroot=\/opt\/android-ndk-r8\/platforms\/android-9\/arch-arm -I. -g -march=armv6j -mtune=arm1136j-s -msoft-float android.c -o android\r\n#include &lt;stdio.h&gt;\r\n#include &lt;string.h&gt;\r\n#include &lt;pthread.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n\r\n\/* getdelim and getline courtesy of VLC's compat\/getdelim.c *\/\r\nssize_t getdelim(char**v1,size_t*v2,int v3,FILE*v4){char*A1=*v1;size_t A2=(A1 != NULL)?*v2:0;size_t A3 = 0;for(;;){if((A2 - A3) &lt;= 2){A2=A2?(A2*2):256;A1=realloc(*v1,A2);if(A1 ==NULL)return-1;*v1=A1;*v2=A2;}int c=fgetc(v4);if(c==-1){if(A3==0||ferror(v4))return -1;break;}A1[A3++]=c;if(c==v3)break;}A1[A3]='&#92;&#48;';return A3;} ssize_t getline(char** a,size_t* b,FILE* c){return getdelim(a,b,'\\n',c);}\r\n\r\nstatic uint32_t cpu_flags = 0;\r\n\r\nstatic void vlc_CPU_init (void) {\r\n    FILE *info = fopen (&quot;\/proc\/cpuinfo&quot;, &quot;rt&quot;);\r\n    if (info == NULL) return;\r\n    char *line = NULL;\r\n    size_t linelen = 0;\r\n\t\/\/ ...irrelevant code skipped...\r\n    while (getline (&amp;line, &amp;linelen, info) != -1) {\r\n        \/\/ ...do stuff with the loop...\r\n    }\r\n    fclose(info); \/* hangs here *\/\r\n    free(line);\r\n\t\/\/ ...parse and set cpu_flags...\r\n    cpu_flags = 1;\r\n}\r\n\r\nunsigned vlc_CPU(void) {\r\n    static pthread_once_t once = PTHREAD_ONCE_INIT;\r\n    pthread_once (&amp;once, vlc_CPU_init);\r\n    \/\/vlc_CPU_init();\r\n    return cpu_flags;\r\n}\r\n\r\nint main(void) {\r\n    if(vlc_CPU() &gt; 0)\r\n        puts(&quot;Successful&quot;);\r\n    else\r\n        puts(&quot;Failure, or a.k.a. will never reach here&quot;);\r\n    return 0;\r\n}\r\n<\/pre>\n<p>Interestingly, after debugging there are two ways to workaround this bug:<\/p>\n<ol>\n<li>Comment out the fclose() on line 21 above, <em><strong><span style=\"text-decoration: underline;\">or<\/span><\/strong><\/em><\/li>\n<li>Don&#8217;t run vlc_CPU_init() inside a thread \u2013 comment out line 29 and uncomment line 30 to run vlc_CPU_init() unthreaded.<\/li>\n<\/ol>\n<p><a href=\"http:\/\/stackoverflow.com\/questions\/9219642\/fclose-hang-after-cloned-threads-on-linux\">Further research<\/a> &#8211; \u201cThe stdio library uses locks internally\u201d &#8211; yields that this may be a bug in bionic, Android&#8217;s own custom implementation of libc as well as pthreads. So far, the fact that fclose() works successfully if not run inside a pthread, as well as the knowledge that stdio has internal locks, may suggest a bug in the bionic implementation on Android 2.2 \/ 2.1 and below.<\/p>\n<p>See also <a href=\"http:\/\/code.google.com\/p\/android\/issues\/detail?id=5116\">http:\/\/code.google.com\/p\/android\/issues\/detail?id=5116<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>There appears to be an obscure bug that has somehow recently activated on ARMv6, non-FPU builds of VLC for Android. This has been only observed on Android 2.1 and possibly on other Android 2.x platforms with ARMv6, non-FPU builds Android 2.2. On the other hand, it works perfectly on an Android 4.0 on a NEON [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[],"_links":{"self":[{"href":"http:\/\/www.compdigitec.com\/labs\/wp-json\/wp\/v2\/posts\/293"}],"collection":[{"href":"http:\/\/www.compdigitec.com\/labs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.compdigitec.com\/labs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.compdigitec.com\/labs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.compdigitec.com\/labs\/wp-json\/wp\/v2\/comments?post=293"}],"version-history":[{"count":0,"href":"http:\/\/www.compdigitec.com\/labs\/wp-json\/wp\/v2\/posts\/293\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.compdigitec.com\/labs\/wp-json\/wp\/v2\/media?parent=293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.compdigitec.com\/labs\/wp-json\/wp\/v2\/categories?post=293"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.compdigitec.com\/labs\/wp-json\/wp\/v2\/tags?post=293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}