« Enabling icons in Qt4 apps on GNOME / GTK | Home | When git am fails, use 3way »
fclose() freezes/hangs when run inside pthread on Android 2.1
By admin | June 25, 2012
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 device (same code), so it is probably specific to Android 2.2 and 2.1 (not tested on 1.6).
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 Android 2.1, no-FPU, no-NEON device. Further testing with the Android emulator also revealed that the Android 2.1 and 2.2 emulator 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 src/posix/linux_cpu.c:
// 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 #include <stdio.h> #include <string.h> #include <pthread.h> #include <stdlib.h> /* getdelim and getline courtesy of VLC's compat/getdelim.c */ ssize_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) <= 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]='\0';return A3;} ssize_t getline(char** a,size_t* b,FILE* c){return getdelim(a,b,'\n',c);} static uint32_t cpu_flags = 0; static void vlc_CPU_init (void) { FILE *info = fopen ("/proc/cpuinfo", "rt"); if (info == NULL) return; char *line = NULL; size_t linelen = 0; // ...irrelevant code skipped... while (getline (&line, &linelen, info) != -1) { // ...do stuff with the loop... } fclose(info); /* hangs here */ free(line); // ...parse and set cpu_flags... cpu_flags = 1; } unsigned vlc_CPU(void) { static pthread_once_t once = PTHREAD_ONCE_INIT; pthread_once (&once, vlc_CPU_init); //vlc_CPU_init(); return cpu_flags; } int main(void) { if(vlc_CPU() > 0) puts("Successful"); else puts("Failure, or a.k.a. will never reach here"); return 0; }
Interestingly, after debugging there are two ways to workaround this bug:
- Comment out the fclose() on line 21 above, or
- Don’t run vlc_CPU_init() inside a thread – comment out line 29 and uncomment line 30 to run vlc_CPU_init() unthreaded.
Further research – “The stdio library uses locks internally” – yields that this may be a bug in bionic, Android’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.
See also http://code.google.com/p/android/issues/detail?id=5116.
If you found this article helpful or interesting, please help Compdigitec spread the word. Don’t forget to subscribe to Compdigitec Labs for more useful and interesting articles!
Topics: Linux | 3 Comments »
November 8th, 2024 at 07:25
… [Trackback]
[…] Information to that Topic: compdigitec.com/labs/2012/06/25/fclose-freezes-when-run-inside-pthread-on-android-2-1/ […]
November 14th, 2024 at 14:21
… [Trackback]
[…] There you will find 14723 more Info to that Topic: compdigitec.com/labs/2012/06/25/fclose-freezes-when-run-inside-pthread-on-android-2-1/ […]
November 16th, 2024 at 05:51
… [Trackback]
[…] Here you can find 62132 more Info to that Topic: compdigitec.com/labs/2012/06/25/fclose-freezes-when-run-inside-pthread-on-android-2-1/ […]