View Issue Details

IDProjectCategoryView StatusLast Update
0021525FPCRTLpublic2013-03-05 20:15
ReporterAndruAssigned ToThomas Schatzl 
PrioritynormalSeveritymajorReproducibilityalways
Status closedResolutionfixed 
PlatformARMOSAndroidOS Version
Product Version2.6.1Product Build 
Target VersionFixed in Version3.0.0 
Summary0021525: [patch]Threads don't work on Android
DescriptionHere is a patch for initc, pthread and cthreads units. Also packages/pthreads/src/pthrlinux.inc need the same modification with hiding unsupported functions on Android platform.

There is an issue with CKillThread, which is need further investigation. Currently pthread_cancel replaced with pthread_kill with signal SIGKILL, but seems people are using signal SIGUSR1 instead with handling sigaction.
TagsNo tags attached.
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files
  • android_pthreads.patch (10,883 bytes)
    --- rtl/linux/pthread.inc
    +++ rtl/linux/pthread.inc
    @@ -126,8 +126,10 @@
         function pthread_attr_getschedparam(__attr:ppthread_attr_t; __param:psched_param):longint;cdecl;external;
         function pthread_attr_setschedpolicy(__attr:ppthread_attr_t; __policy:longint):longint;cdecl;external;
         function pthread_attr_getschedpolicy(__attr:ppthread_attr_t; __policy:plongint):longint;cdecl;external;
    +    {$IFNDEF ANDROID}
         function pthread_attr_setinheritsched(__attr:ppthread_attr_t; __inherit:longint):longint;cdecl;external;
         function pthread_attr_getinheritsched(__attr:ppthread_attr_t; __inherit:plongint):longint;cdecl;external;
    +    {$ENDIF}
         function pthread_attr_setstacksize(p: ppthread_attr_t;s:size_t):cint;cdecl;external;
         function pthread_attr_getstacksize(p: ppthread_attr_t;s:psize_t):cint;cdecl;external;
         function pthread_attr_setscope(__attr:ppthread_attr_t; __scope:longint):longint;cdecl;external;
    @@ -197,8 +199,10 @@
         pthread_attr_getschedparam : Function(__attr:ppthread_attr_t; __param:psched_param):longint;cdecl;
         pthread_attr_setschedpolicy : Function(__attr:ppthread_attr_t; __policy:longint):longint;cdecl;
         pthread_attr_getschedpolicy : Function(__attr:ppthread_attr_t; __policy:plongint):longint;cdecl;
    +    {$IFNDEF ANDROID}
         pthread_attr_setinheritsched : Function(__attr:ppthread_attr_t; __inherit:longint):longint;cdecl;
         pthread_attr_getinheritsched : Function(__attr:ppthread_attr_t; __inherit:plongint):longint;cdecl;
    +    {$ENDIF}
         pthread_attr_setscope : Function(__attr:ppthread_attr_t; __scope:longint):longint;cdecl;
         pthread_attr_getscope : Function(__attr:ppthread_attr_t; __scope:plongint):longint;cdecl;
         pthread_setschedparam : Function(__target_thread:pthread_t; __policy:longint; __param:psched_param):longint;cdecl;
    @@ -211,32 +215,40 @@
         pthread_mutex_unlock : Function(__mutex:ppthread_mutex_t):longint;cdecl;
         pthread_mutexattr_init : Function(__attr:ppthread_mutexattr_t):longint;cdecl;
         pthread_mutexattr_destroy : Function(__attr:ppthread_mutexattr_t):longint;cdecl;
    +    {$IFNDEF ANDROID}
         pthread_mutexattr_setkind_np : Function(__attr:ppthread_mutexattr_t; __kind:longint):longint;cdecl;
         pthread_mutexattr_getkind_np : Function(__attr:ppthread_mutexattr_t; __kind:plongint):longint;cdecl;
    +    {$ENDIF}
         pthread_cond_init : Function(__cond:ppthread_cond_t; __cond_attr:ppthread_condattr_t):longint;cdecl;
         pthread_cond_destroy : Function(__cond:ppthread_cond_t):longint;cdecl;
         pthread_cond_signal : Function(__cond:ppthread_cond_t):longint;cdecl;
         pthread_cond_broadcast : Function(__cond:ppthread_cond_t):longint;cdecl;
         pthread_cond_wait : Function(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t):longint;cdecl;
         pthread_cond_timedwait : Function(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t; __abstime:ptimespec):longint;cdecl;
    +    {$IFNDEF ANDROID}
         pthread_condattr_init : Function(__attr:ppthread_condattr_t):longint;cdecl;
         pthread_condattr_destroy : Function(__attr:ppthread_condattr_t):longint;cdecl;
    +    {$ENDIF}
         pthread_key_create : Function(__key:ppthread_key_t; __destr_function:__destr_function_t):longint;cdecl;
         pthread_key_delete : Function(__key:pthread_key_t):longint;cdecl;
         pthread_setspecific : Function(__key:pthread_key_t; __pointer:pointer):longint;cdecl;
         pthread_getspecific : Function(__key:pthread_key_t):pointer;cdecl;
     {    pthread_once : Function(__once_control:ppthread_once_t; __init_routine:tprocedure ):longint;cdecl;}
    +    {$IFNDEF ANDROID}
         pthread_setcancelstate : Function(__state:longint; __oldstate:plongint):longint;cdecl;
         pthread_setcanceltype : Function(__type:longint; __oldtype:plongint):longint;cdecl;
         pthread_cancel : Function(__thread:pthread_t):longint;cdecl;
         pthread_testcancel : Procedure ;cdecl;
    +    {$ENDIF}
     {    _pthread_cleanup_push : procedure (__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_routine; __arg:pointer);cdecl;}
     {    _pthread_cleanup_push_defer : procedure (__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_defer_routine; __arg:pointer);cdecl;}
     {    pthread_sigmask : Function(__how:longint; __newmask:plibc_sigset; __oldmask:plibc_sigset):longint;cdecl;}
         pthread_kill : Function(__thread:pthread_t; __signo:longint):longint;cdecl;
     {    sigwait : Function(__set:plibc_sigset; __sig:plongint):longint;cdecl;}
    +    {$IFNDEF ANDROID}
         pthread_atfork : Function(__prepare:tprocedure ; __parent:tprocedure ; __child:tprocedure ):longint;cdecl;
         pthread_kill_other_threads_np : procedure;cdecl;
    +    {$ENDIF}
         pthread_sigmask: Function(how: cint; nset: plibc_sigset; oset: plibc_sigset): cint;cdecl;
     
         sem_init     :   function (__sem:Psem_t; __pshared:longint; __value:dword):longint;cdecl;
    @@ -258,7 +270,11 @@
     Function LoadPthreads : Boolean;
     
     begin
    +  {$IFNDEF ANDROID}
       PThreadDLL:=DlOpen('libpthread.so.0',RTLD_LAZY);
    +  {$ELSE}
    +  PThreadDLL := dlopen( 'libc.so', RTLD_LAZY );
    +  {$ENDIF}
       Result:=PThreadDLL<>Nil;
       If Not Result then
         exit;
    @@ -276,8 +292,10 @@
       Pointer(pthread_attr_getschedparam) := dlsym(PthreadDLL,'pthread_attr_getschedparam');
       Pointer(pthread_attr_setschedpolicy) := dlsym(PthreadDLL,'pthread_attr_setschedpolicy');
       Pointer(pthread_attr_getschedpolicy) := dlsym(PthreadDLL,'pthread_attr_getschedpolicy');
    +  {$IFNDEF ANDROID}
       Pointer(pthread_attr_setinheritsched) := dlsym(PthreadDLL,'pthread_attr_setinheritsched');
       Pointer(pthread_attr_getinheritsched) := dlsym(PthreadDLL,'pthread_attr_getinheritsched');
    +  {$ENDIF}
       Pointer(pthread_attr_setscope) := dlsym(PthreadDLL,'pthread_attr_setscope');
       Pointer(pthread_attr_getscope) := dlsym(PthreadDLL,'pthread_attr_getscope');
       Pointer(pthread_attr_setstacksize) := dlsym(PthreadDLL,'pthread_attr_setstacksize');
    @@ -290,31 +308,39 @@
       Pointer(pthread_mutex_unlock) := dlsym(PthreadDLL,'pthread_mutex_unlock');
       Pointer(pthread_mutexattr_init) := dlsym(PthreadDLL,'pthread_mutexattr_init');
       Pointer(pthread_mutexattr_destroy) := dlsym(PthreadDLL,'pthread_mutexattr_destroy');
    +  {$IFNDEF ANDROID}
       Pointer(pthread_mutexattr_setkind_np) := dlsym(PthreadDLL,'pthread_mutexattr_setkind_np');
       Pointer(pthread_mutexattr_getkind_np) := dlsym(PthreadDLL,'pthread_mutexattr_getkind_np');
    +  {$ENDIF}
       Pointer(pthread_cond_init) := dlsym(PthreadDLL,'pthread_cond_init');
       Pointer(pthread_cond_destroy) := dlsym(PthreadDLL,'pthread_cond_destroy');
       Pointer(pthread_cond_signal) := dlsym(PthreadDLL,'pthread_cond_signal');
       Pointer(pthread_cond_broadcast) := dlsym(PthreadDLL,'pthread_cond_broadcast');
       Pointer(pthread_cond_wait) := dlsym(PthreadDLL,'pthread_cond_wait');
       Pointer(pthread_cond_timedwait) := dlsym(PthreadDLL,'pthread_cond_timedwait');
    +  {$IFNDEF ANDROID}
       Pointer(pthread_condattr_init) := dlsym(PthreadDLL,'pthread_condattr_init');
       Pointer(pthread_condattr_destroy) := dlsym(PthreadDLL,'pthread_condattr_destroy');
    +  {$ENDIF}
       Pointer(pthread_key_create) := dlsym(PthreadDLL,'pthread_key_create');
       Pointer(pthread_key_delete) := dlsym(PthreadDLL,'pthread_key_delete');
       Pointer(pthread_setspecific) := dlsym(PthreadDLL,'pthread_setspecific');
       Pointer(pthread_getspecific) := dlsym(PthreadDLL,'pthread_getspecific');
     {  Pointer(pthread_once) := dlsym(PthreadDLL,'pthread_once');}
    +  {$IFNDEF ANDROID}
       Pointer(pthread_setcancelstate) := dlsym(PthreadDLL,'pthread_setcancelstate');
       Pointer(pthread_setcanceltype) := dlsym(PthreadDLL,'pthread_setcanceltype');
       Pointer(pthread_cancel) := dlsym(PthreadDLL,'pthread_cancel');
       Pointer(pthread_testcancel) := dlsym(PthreadDLL,'pthread_testcancel');
    +  {$ENDIF}
     {  Pointer(_pthread_cleanup_push) := dlsym(PthreadDLL,'_pthread_cleanup_push');}
     {  Pointer(_pthread_cleanup_push_defer) := dlsym(PthreadDLL,'_pthread_cleanup_push_defer');}
     {  Pointer(pthread_sigmask) := dlsym(PthreadDLL,'pthread_sigmask');}
       Pointer(pthread_kill)  := dlsym(PthreadDLL,'pthread_kill');
    +  {$IFNDEF ANDROID}
       Pointer(pthread_atfork):= dlsym(PthreadDLL,'pthread_atfork');
       Pointer(pthread_kill_other_threads_np) := dlsym(PthreadDLL,'pthread_kill_other_threads_np');
    +  {$ENDIF}
       Pointer(pthread_sigmask) := dlsym(PthreadDLL,'pthread_sigmask');
       Pointer(sem_init     ) := dlsym(PthreadDLL,'sem_init');
       Pointer(sem_destroy  ) := dlsym(PthreadDLL,'sem_destroy');
    ===================================================================
    --- rtl/unix/initc.pp
    +++ rtl/unix/initc.pp
    @@ -52,7 +52,7 @@
     
     
     {$ifdef Linux}
    -function geterrnolocation: pcint; cdecl;external clib name '__errno_location';
    +function geterrnolocation: pcint; cdecl;external clib name {$IFNDEF ANDROID}'__errno_location'{$ELSE}'__errno'{$ENDIF};
     {$endif}
     
     {$ifdef FreeBSD} // tested on x86
    ===================================================================
    --- rtl/unix/cthreads.pp
    +++ rtl/unix/cthreads.pp
    @@ -21,8 +21,11 @@
         b) still enabling dynamically checking whether or not certain functions
            are available (could also be implemented via weak linking)
     }
    +{$IFNDEF ANDROID}
     {$linklib pthread}
     {$define dynpthreads} // Useless on BSD, since they are in libc
    +                      // Hangs up on Android
    +{$ENDIF}
     {$endif}
     
     
    @@ -53,7 +56,7 @@
     
     {$ifndef dynpthreads}   // If you have problems compiling this on FreeBSD 5.x
      {$linklib c}           // try adding -Xf
    - {$if not defined(Darwin) and not defined(iphonesim)}
    + {$if not defined(Darwin) and not defined(iphonesim) and not defined(ANDROID)}
        {$ifndef haiku}
          {$linklib pthread}
        {$endif haiku}
    @@ -332,13 +335,13 @@
           writeln('Starting new thread');
     {$endif DEBUG_MT}
           pthread_attr_init(@thread_attr);
    -      {$ifndef HAIKU}
    +      {$if not defined(HAIKU) and not defined(ANDROID)}
           {$ifdef solaris}
           pthread_attr_setinheritsched(@thread_attr, PTHREAD_INHERIT_SCHED);
           {$else not solaris}
           pthread_attr_setinheritsched(@thread_attr, PTHREAD_EXPLICIT_SCHED);
           {$endif not solaris}
    -      {$endif}
    +      {$ifend}
     
           // will fail under linux -- apparently unimplemented
           pthread_attr_setscope(@thread_attr, PTHREAD_SCOPE_PROCESS);
    @@ -409,7 +412,11 @@
       function  CKillThread (threadHandle : TThreadID) : dword;
         begin
           pthread_detach(pthread_t(threadHandle));
    +      {$IFNDEF ANDROID}
           CKillThread := pthread_cancel(pthread_t(threadHandle));
    +      {$ELSE}
    +      pthread_kill(pthread_t(threadHandle),SIGKILL);
    +      {$ENDIF}
         end;
     
       function CCloseThread (threadHandle : TThreadID) : dword;
    @@ -507,7 +514,7 @@
     {*****************************************************************************
                                Semaphore routines
     *****************************************************************************}
    -  
    +
     procedure cSemaphoreWait(const FSem: Pointer);
     var
       res: cint;
    android_pthreads.patch (10,883 bytes)

Relationships

related to 0021853 resolvedYuriy Sydorov IFDEF-conditional Android patch for the arm//linux RTL 

Activities

2012-03-22 00:12

 

android_pthreads.patch (10,883 bytes)
--- rtl/linux/pthread.inc
+++ rtl/linux/pthread.inc
@@ -126,8 +126,10 @@
     function pthread_attr_getschedparam(__attr:ppthread_attr_t; __param:psched_param):longint;cdecl;external;
     function pthread_attr_setschedpolicy(__attr:ppthread_attr_t; __policy:longint):longint;cdecl;external;
     function pthread_attr_getschedpolicy(__attr:ppthread_attr_t; __policy:plongint):longint;cdecl;external;
+    {$IFNDEF ANDROID}
     function pthread_attr_setinheritsched(__attr:ppthread_attr_t; __inherit:longint):longint;cdecl;external;
     function pthread_attr_getinheritsched(__attr:ppthread_attr_t; __inherit:plongint):longint;cdecl;external;
+    {$ENDIF}
     function pthread_attr_setstacksize(p: ppthread_attr_t;s:size_t):cint;cdecl;external;
     function pthread_attr_getstacksize(p: ppthread_attr_t;s:psize_t):cint;cdecl;external;
     function pthread_attr_setscope(__attr:ppthread_attr_t; __scope:longint):longint;cdecl;external;
@@ -197,8 +199,10 @@
     pthread_attr_getschedparam : Function(__attr:ppthread_attr_t; __param:psched_param):longint;cdecl;
     pthread_attr_setschedpolicy : Function(__attr:ppthread_attr_t; __policy:longint):longint;cdecl;
     pthread_attr_getschedpolicy : Function(__attr:ppthread_attr_t; __policy:plongint):longint;cdecl;
+    {$IFNDEF ANDROID}
     pthread_attr_setinheritsched : Function(__attr:ppthread_attr_t; __inherit:longint):longint;cdecl;
     pthread_attr_getinheritsched : Function(__attr:ppthread_attr_t; __inherit:plongint):longint;cdecl;
+    {$ENDIF}
     pthread_attr_setscope : Function(__attr:ppthread_attr_t; __scope:longint):longint;cdecl;
     pthread_attr_getscope : Function(__attr:ppthread_attr_t; __scope:plongint):longint;cdecl;
     pthread_setschedparam : Function(__target_thread:pthread_t; __policy:longint; __param:psched_param):longint;cdecl;
@@ -211,32 +215,40 @@
     pthread_mutex_unlock : Function(__mutex:ppthread_mutex_t):longint;cdecl;
     pthread_mutexattr_init : Function(__attr:ppthread_mutexattr_t):longint;cdecl;
     pthread_mutexattr_destroy : Function(__attr:ppthread_mutexattr_t):longint;cdecl;
+    {$IFNDEF ANDROID}
     pthread_mutexattr_setkind_np : Function(__attr:ppthread_mutexattr_t; __kind:longint):longint;cdecl;
     pthread_mutexattr_getkind_np : Function(__attr:ppthread_mutexattr_t; __kind:plongint):longint;cdecl;
+    {$ENDIF}
     pthread_cond_init : Function(__cond:ppthread_cond_t; __cond_attr:ppthread_condattr_t):longint;cdecl;
     pthread_cond_destroy : Function(__cond:ppthread_cond_t):longint;cdecl;
     pthread_cond_signal : Function(__cond:ppthread_cond_t):longint;cdecl;
     pthread_cond_broadcast : Function(__cond:ppthread_cond_t):longint;cdecl;
     pthread_cond_wait : Function(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t):longint;cdecl;
     pthread_cond_timedwait : Function(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t; __abstime:ptimespec):longint;cdecl;
+    {$IFNDEF ANDROID}
     pthread_condattr_init : Function(__attr:ppthread_condattr_t):longint;cdecl;
     pthread_condattr_destroy : Function(__attr:ppthread_condattr_t):longint;cdecl;
+    {$ENDIF}
     pthread_key_create : Function(__key:ppthread_key_t; __destr_function:__destr_function_t):longint;cdecl;
     pthread_key_delete : Function(__key:pthread_key_t):longint;cdecl;
     pthread_setspecific : Function(__key:pthread_key_t; __pointer:pointer):longint;cdecl;
     pthread_getspecific : Function(__key:pthread_key_t):pointer;cdecl;
 {    pthread_once : Function(__once_control:ppthread_once_t; __init_routine:tprocedure ):longint;cdecl;}
+    {$IFNDEF ANDROID}
     pthread_setcancelstate : Function(__state:longint; __oldstate:plongint):longint;cdecl;
     pthread_setcanceltype : Function(__type:longint; __oldtype:plongint):longint;cdecl;
     pthread_cancel : Function(__thread:pthread_t):longint;cdecl;
     pthread_testcancel : Procedure ;cdecl;
+    {$ENDIF}
 {    _pthread_cleanup_push : procedure (__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_routine; __arg:pointer);cdecl;}
 {    _pthread_cleanup_push_defer : procedure (__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_defer_routine; __arg:pointer);cdecl;}
 {    pthread_sigmask : Function(__how:longint; __newmask:plibc_sigset; __oldmask:plibc_sigset):longint;cdecl;}
     pthread_kill : Function(__thread:pthread_t; __signo:longint):longint;cdecl;
 {    sigwait : Function(__set:plibc_sigset; __sig:plongint):longint;cdecl;}
+    {$IFNDEF ANDROID}
     pthread_atfork : Function(__prepare:tprocedure ; __parent:tprocedure ; __child:tprocedure ):longint;cdecl;
     pthread_kill_other_threads_np : procedure;cdecl;
+    {$ENDIF}
     pthread_sigmask: Function(how: cint; nset: plibc_sigset; oset: plibc_sigset): cint;cdecl;
 
     sem_init     :   function (__sem:Psem_t; __pshared:longint; __value:dword):longint;cdecl;
@@ -258,7 +270,11 @@
 Function LoadPthreads : Boolean;
 
 begin
+  {$IFNDEF ANDROID}
   PThreadDLL:=DlOpen('libpthread.so.0',RTLD_LAZY);
+  {$ELSE}
+  PThreadDLL := dlopen( 'libc.so', RTLD_LAZY );
+  {$ENDIF}
   Result:=PThreadDLL<>Nil;
   If Not Result then
     exit;
@@ -276,8 +292,10 @@
   Pointer(pthread_attr_getschedparam) := dlsym(PthreadDLL,'pthread_attr_getschedparam');
   Pointer(pthread_attr_setschedpolicy) := dlsym(PthreadDLL,'pthread_attr_setschedpolicy');
   Pointer(pthread_attr_getschedpolicy) := dlsym(PthreadDLL,'pthread_attr_getschedpolicy');
+  {$IFNDEF ANDROID}
   Pointer(pthread_attr_setinheritsched) := dlsym(PthreadDLL,'pthread_attr_setinheritsched');
   Pointer(pthread_attr_getinheritsched) := dlsym(PthreadDLL,'pthread_attr_getinheritsched');
+  {$ENDIF}
   Pointer(pthread_attr_setscope) := dlsym(PthreadDLL,'pthread_attr_setscope');
   Pointer(pthread_attr_getscope) := dlsym(PthreadDLL,'pthread_attr_getscope');
   Pointer(pthread_attr_setstacksize) := dlsym(PthreadDLL,'pthread_attr_setstacksize');
@@ -290,31 +308,39 @@
   Pointer(pthread_mutex_unlock) := dlsym(PthreadDLL,'pthread_mutex_unlock');
   Pointer(pthread_mutexattr_init) := dlsym(PthreadDLL,'pthread_mutexattr_init');
   Pointer(pthread_mutexattr_destroy) := dlsym(PthreadDLL,'pthread_mutexattr_destroy');
+  {$IFNDEF ANDROID}
   Pointer(pthread_mutexattr_setkind_np) := dlsym(PthreadDLL,'pthread_mutexattr_setkind_np');
   Pointer(pthread_mutexattr_getkind_np) := dlsym(PthreadDLL,'pthread_mutexattr_getkind_np');
+  {$ENDIF}
   Pointer(pthread_cond_init) := dlsym(PthreadDLL,'pthread_cond_init');
   Pointer(pthread_cond_destroy) := dlsym(PthreadDLL,'pthread_cond_destroy');
   Pointer(pthread_cond_signal) := dlsym(PthreadDLL,'pthread_cond_signal');
   Pointer(pthread_cond_broadcast) := dlsym(PthreadDLL,'pthread_cond_broadcast');
   Pointer(pthread_cond_wait) := dlsym(PthreadDLL,'pthread_cond_wait');
   Pointer(pthread_cond_timedwait) := dlsym(PthreadDLL,'pthread_cond_timedwait');
+  {$IFNDEF ANDROID}
   Pointer(pthread_condattr_init) := dlsym(PthreadDLL,'pthread_condattr_init');
   Pointer(pthread_condattr_destroy) := dlsym(PthreadDLL,'pthread_condattr_destroy');
+  {$ENDIF}
   Pointer(pthread_key_create) := dlsym(PthreadDLL,'pthread_key_create');
   Pointer(pthread_key_delete) := dlsym(PthreadDLL,'pthread_key_delete');
   Pointer(pthread_setspecific) := dlsym(PthreadDLL,'pthread_setspecific');
   Pointer(pthread_getspecific) := dlsym(PthreadDLL,'pthread_getspecific');
 {  Pointer(pthread_once) := dlsym(PthreadDLL,'pthread_once');}
+  {$IFNDEF ANDROID}
   Pointer(pthread_setcancelstate) := dlsym(PthreadDLL,'pthread_setcancelstate');
   Pointer(pthread_setcanceltype) := dlsym(PthreadDLL,'pthread_setcanceltype');
   Pointer(pthread_cancel) := dlsym(PthreadDLL,'pthread_cancel');
   Pointer(pthread_testcancel) := dlsym(PthreadDLL,'pthread_testcancel');
+  {$ENDIF}
 {  Pointer(_pthread_cleanup_push) := dlsym(PthreadDLL,'_pthread_cleanup_push');}
 {  Pointer(_pthread_cleanup_push_defer) := dlsym(PthreadDLL,'_pthread_cleanup_push_defer');}
 {  Pointer(pthread_sigmask) := dlsym(PthreadDLL,'pthread_sigmask');}
   Pointer(pthread_kill)  := dlsym(PthreadDLL,'pthread_kill');
+  {$IFNDEF ANDROID}
   Pointer(pthread_atfork):= dlsym(PthreadDLL,'pthread_atfork');
   Pointer(pthread_kill_other_threads_np) := dlsym(PthreadDLL,'pthread_kill_other_threads_np');
+  {$ENDIF}
   Pointer(pthread_sigmask) := dlsym(PthreadDLL,'pthread_sigmask');
   Pointer(sem_init     ) := dlsym(PthreadDLL,'sem_init');
   Pointer(sem_destroy  ) := dlsym(PthreadDLL,'sem_destroy');
===================================================================
--- rtl/unix/initc.pp
+++ rtl/unix/initc.pp
@@ -52,7 +52,7 @@
 
 
 {$ifdef Linux}
-function geterrnolocation: pcint; cdecl;external clib name '__errno_location';
+function geterrnolocation: pcint; cdecl;external clib name {$IFNDEF ANDROID}'__errno_location'{$ELSE}'__errno'{$ENDIF};
 {$endif}
 
 {$ifdef FreeBSD} // tested on x86
===================================================================
--- rtl/unix/cthreads.pp
+++ rtl/unix/cthreads.pp
@@ -21,8 +21,11 @@
     b) still enabling dynamically checking whether or not certain functions
        are available (could also be implemented via weak linking)
 }
+{$IFNDEF ANDROID}
 {$linklib pthread}
 {$define dynpthreads} // Useless on BSD, since they are in libc
+                      // Hangs up on Android
+{$ENDIF}
 {$endif}
 
 
@@ -53,7 +56,7 @@
 
 {$ifndef dynpthreads}   // If you have problems compiling this on FreeBSD 5.x
  {$linklib c}           // try adding -Xf
- {$if not defined(Darwin) and not defined(iphonesim)}
+ {$if not defined(Darwin) and not defined(iphonesim) and not defined(ANDROID)}
    {$ifndef haiku}
      {$linklib pthread}
    {$endif haiku}
@@ -332,13 +335,13 @@
       writeln('Starting new thread');
 {$endif DEBUG_MT}
       pthread_attr_init(@thread_attr);
-      {$ifndef HAIKU}
+      {$if not defined(HAIKU) and not defined(ANDROID)}
       {$ifdef solaris}
       pthread_attr_setinheritsched(@thread_attr, PTHREAD_INHERIT_SCHED);
       {$else not solaris}
       pthread_attr_setinheritsched(@thread_attr, PTHREAD_EXPLICIT_SCHED);
       {$endif not solaris}
-      {$endif}
+      {$ifend}
 
       // will fail under linux -- apparently unimplemented
       pthread_attr_setscope(@thread_attr, PTHREAD_SCOPE_PROCESS);
@@ -409,7 +412,11 @@
   function  CKillThread (threadHandle : TThreadID) : dword;
     begin
       pthread_detach(pthread_t(threadHandle));
+      {$IFNDEF ANDROID}
       CKillThread := pthread_cancel(pthread_t(threadHandle));
+      {$ELSE}
+      pthread_kill(pthread_t(threadHandle),SIGKILL);
+      {$ENDIF}
     end;
 
   function CCloseThread (threadHandle : TThreadID) : dword;
@@ -507,7 +514,7 @@
 {*****************************************************************************
                            Semaphore routines
 *****************************************************************************}
-  
+
 procedure cSemaphoreWait(const FSem: Pointer);
 var
   res: cint;
android_pthreads.patch (10,883 bytes)

Jonas Maebe

2012-03-22 00:29

manager   ~0057890

> Currently pthread_cancel replaced with pthread_kill with signal SIGKILL

That is wrong. SIGKILL will always affect the entire process, not just a single thread (except maybe in the old linuxthreads implementation). See e.g. http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Fapis%2Fusers_95.htm and http://books.google.be/books?id=TXiJDj9kbiAC&lpg=PA217&ots=ny8AGfrDBd&dq=%22pthread_kill%22%20%22SIGKILL%22&hl=nl&pg=PA217#v=onepage&q=%22pthread_kill%22%20%22SIGKILL%22&f=false

Additionally, asynchronously halting a thread in the middle of its execution is extremely bad programming, because it often leads to deadlocks or other inconsistent program states. It has been removed from several programming language environments that used to support it (such as Java), and is also deprecated in current Delphi versions afaik.

pthread_cancel() is the only correct API that can be used. If Android does not support it (which would be strange, since it's part of the official POSIX specs), then it probably has a proprietary replacement api (most likely in the pthread_<xxx>_np family).

Andru

2012-03-22 00:39

reporter   ~0057891

Last edited: 2012-03-22 00:49

>> That is wrong
I know that it is wrong, and I wrote about that :)

>> If Android does not support it (which would be strange, since it's part of the official POSIX specs), then it probably has a proprietary replacement api (most likely in the pthread_<xxx>_np family).
I investigate the problem, and yes, there is no pthread_cancel on Android(exactly in Bionic, there was some patch, but it was not accepted). And there are two popular solutions:
- avoiding killing threads or using "safe" code in threads
- pthread_kill with handling sigaction, but I didn't investigate it deeper

Anyway here is a "beginning" and changes will be good to have from FPC Developers team :)

Jonas Maebe

2012-03-22 00:48

manager   ~0057892

> I know that it is wrong, and I wrote about that, don't be an Captain Obvious

It is not obvious to me why you submit a patch of which you know that it is wrong. Changing the code from something that probably errors out with a calling a nil pointer (so you can at least know where things go wrong) into something that simply terminates the program makes things worse, not better.

> - pthread_kill with handling sigaction, but I didn't investigate it deeper

It is impossible to handle SIGKILL with sigaction. Together with SIGCONT and SIGSTOP, those are the only signals that a program cannot intercept (otherwise it would be impossible to force-kill a process, or to pause and continue it).

And as mentioned in my previous comment: it is fundamentally wrong programming to asynchronously terminate a thread. Support for that will never be added to the RTL, regardless of how you implement it (you could indeed do it with SIGUSR1 or so, provided that the program itself doesn't use that signal for another purpose, but that will not be added to the RTL).

Andru

2012-03-22 00:54

reporter   ~0057893

>> It is impossible to handle SIGKILL with sigaction.
In text above I mentioned SIGUSR1 for handling sigaction

>> It is not obvious to me why you submit a patch of which you know that it is wrong
This is maybe wrong from my side, anyway I mentioned about the problem which is need to be solved.

>> And as mentioned in my previous comment: it is fundamentally wrong programming to asynchronously terminate a thread. Support for that will never be added to the RTL, regardless of how you implement it (you could indeed do it with SIGUSR1 or so, provided that the program itself doesn't use that signal for another purpose, but that will not be added to the RTL).
Ok, have no more questions.

Yuriy Sydorov

2013-03-05 01:12

manager   ~0066013

All valid parts of your patch is in trunk now.

Andru

2013-03-05 20:15

reporter   ~0066035

Thanks

Issue History

Date Modified Username Field Change
2012-03-22 00:12 Andru New Issue
2012-03-22 00:12 Andru File Added: android_pthreads.patch
2012-03-22 00:29 Jonas Maebe Note Added: 0057890
2012-03-22 00:39 Andru Note Added: 0057891
2012-03-22 00:40 Andru Note Edited: 0057891
2012-03-22 00:48 Andru Note Edited: 0057891
2012-03-22 00:48 Jonas Maebe Note Added: 0057892
2012-03-22 00:49 Andru Note Edited: 0057891
2012-03-22 00:54 Andru Note Added: 0057893
2012-04-26 15:25 Thomas Schatzl Relationship added related to 0021853
2012-07-07 22:55 Thomas Schatzl Status new => assigned
2012-07-07 22:55 Thomas Schatzl Assigned To => Thomas Schatzl
2013-03-05 01:12 Yuriy Sydorov Note Added: 0066013
2013-03-05 01:12 Yuriy Sydorov Status assigned => resolved
2013-03-05 01:12 Yuriy Sydorov Fixed in Version => 2.7.1
2013-03-05 01:12 Yuriy Sydorov Resolution open => fixed
2013-03-05 20:15 Andru Note Added: 0066035
2013-03-05 20:15 Andru Status resolved => closed