瀏覽代碼

* android: Fixed crash when using writeln during shared library finalization on Android 4.4+.

git-svn-id: trunk@32033 -
yury 9 年之前
父節點
當前提交
63813f3e96

+ 1 - 0
.gitattributes

@@ -8113,6 +8113,7 @@ rtl/android/jvm/java_sysh_android.inc svneol=native#text/plain
 rtl/android/jvm/rtl.cfg svneol=native#text/plain
 rtl/android/mipsel/dllprt0.as svneol=native#text/plain
 rtl/android/mipsel/prt0.as svneol=native#text/plain
+rtl/android/sysandroid.inc svneol=native#text/plain
 rtl/arm/arm.inc svneol=native#text/plain
 rtl/arm/armdefines.inc svneol=native#text/plain
 rtl/arm/divide.inc svneol=native#text/plain

+ 1 - 0
rtl/android/Makefile

@@ -3543,6 +3543,7 @@ endif
 .NOTPARALLEL:
 include $(INC)/makefile.inc
 SYSINCDEPS=$(addprefix $(INC)/,$(SYSINCNAMES))
+SYSINCDEPS:=$(SYSINCDEPS) sysandroid.inc
 include $(PROCINC)/makefile.cpu
 SYSCPUDEPS=$(addprefix $(PROCINC)/,$(CPUINCNAMES))
 SYSDEPS=$(SYSINCDEPS) $(SYSCPUDEPS)

+ 1 - 0
rtl/android/Makefile.fpc

@@ -83,6 +83,7 @@ OBJPASDIR=$(RTL)/objpas
 # SYSINCNAMES
 include $(INC)/makefile.inc
 SYSINCDEPS=$(addprefix $(INC)/,$(SYSINCNAMES))
+SYSINCDEPS:=$(SYSINCDEPS) sysandroid.inc
 
 # Get the processor dependent include file names.
 # This will set the following variables :

+ 4 - 8
rtl/android/arm/dllprt0.as

@@ -45,14 +45,12 @@ FPC_SHARED_LIB_START:
         ldr ip,.Loperatingsystem_parameter_envp
         ldr ip,[r3, ip]
         str r0,[ip]
-        
-        /* Register exit handler. It is called only when the main process terminates */
-        ldr r0,.LFPC_LIB_EXIT
-        ldr r0,[r3, r0]
-        blx atexit
 
-        /* call main and exit normally */
+        /* Call main */
         blx PASCALMAIN
+        /* Call library init */
+        blx FPC_LIB_INIT_ANDROID
+
         ldmea fp, {fp, sp, pc}
 
 .L_GOT1:
@@ -65,8 +63,6 @@ FPC_SHARED_LIB_START:
         .word EmptyEnv(GOT)
 .Loperatingsystem_parameter_envp:
         .word operatingsystem_parameter_envp(GOT)
-.LFPC_LIB_EXIT:
-        .word FPC_LIB_EXIT(GOT)
 
 /* --------------------------------------------------------- */
         .globl  _haltproc

+ 4 - 7
rtl/android/i386/dllprt0.as

@@ -47,17 +47,14 @@ env_ok:
         movl    operatingsystem_parameter_envp@GOT(%ebx),%edx
         movl    %eax,(%edx)
 
-        /* Register exit handler. It is called only when the main process terminates */
-        movl    FPC_LIB_EXIT@GOT(%ebx),%eax
-        pushl   %eax
-        call    atexit@PLT
-        addl    $4,%esp
-
         /* Restore ebx */
         popl    %ebx
 
-        /* call main and exit normally */
+        /* Call main */
         call    PASCALMAIN@PLT
+        /* Call library init */
+        call    FPC_LIB_INIT_ANDROID@PLT
+
         leave
         ret
 

+ 4 - 6
rtl/android/mipsel/dllprt0.as

@@ -43,14 +43,12 @@ GotEnv:
     la $t1, operatingsystem_parameter_envp
     sw $t0, ($t1)
 
-    /* Register exit handler */
-    la $a0, FPC_LIB_EXIT
-    jal atexit
-    nop
-
-    /* Call main, exit */
+    /* Call main */
     jal PASCALMAIN
     nop
+    /* Call library init */
+    jal FPC_LIB_INIT_ANDROID
+    nop
 
     /* restore registers, exit */
     lw $ra, 24($sp)

+ 60 - 0
rtl/android/sysandroid.inc

@@ -0,0 +1,60 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2015 by Yury Sidorov,
+    member of the Free Pascal development team.
+
+    Android-specific part of the System unit.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ **********************************************************************}
+
+procedure atexit(p: pointer); cdecl; external;
+
+var
+  _SaveStdOut: THandle;
+  _SaveStdErr: THandle;
+
+procedure SysAndroidLibExit; cdecl;
+var
+  ioclosed: boolean;
+begin
+  // Check if stdio is closed now
+  ioclosed:=do_syscall(syscall_nr_fcntl, TSysParam(1), 1 {F_GETFD}) = -1;
+  // If stdio is closed, restore stdout and stderr
+  if ioclosed then
+    begin
+      FpDup2(_SaveStdOut, 1);
+      FpDup2(_SaveStdErr, 2);
+    end;
+  // Close saved handles
+  FpClose(_SaveStdOut);
+  FpClose(_SaveStdErr);
+  // Finalize the library
+  lib_exit;
+  // Close stdout and stderr if stdio has been closed
+  if ioclosed then
+    begin
+      FpClose(1);
+      FpClose(2);
+    end;
+end;
+
+procedure SysInitAndroidLib; [public, alias:'FPC_LIB_INIT_ANDROID'];
+begin
+  { Starting from Android 4.4 stdio handles are closed by libc prior to calling
+    finalization routines of shared libraries. This causes a error while trying to
+    writeln during library finalization and finally a crash because the error can
+    not be printer too.
+    It is needed to save stdout and stderr handles by duplicating them and restore
+    them before library finalization.
+  }
+  _SaveStdOut:=FpDup(1);
+  _SaveStdErr:=FpDup(2);
+  // Register the finalization routine
+  atexit(@SysAndroidLibExit);
+end;

+ 4 - 0
rtl/linux/system.pp

@@ -77,6 +77,10 @@ const calculated_cmdline:Pchar=nil;
 
 {$I system.inc}
 
+{$ifdef android}
+{$I sysandroid.inc}
+{$endif android}
+
 {*****************************************************************************
                        Misc. System Dependent Functions
 *****************************************************************************}