Android 10自定义服务首次烧录镜像后调用localtime崩溃求助
问题
在Android 10环境下,自定义服务中执行以下代码时出现崩溃,仅首次烧录镜像时触发,重启设备后恢复正常:
time_t curr; struct tm *tTM = NULL; char pcurDate[24] = {0}; time(&curr); LOG_I("[getClearAttackStamp][%d]:curr = %ld.\r\n",__LINE__,curr); tTM = localtime(&curr); LOG_I("[%s][%d]: %4d-%02d-%02d %02d:%02d:%02d.\r\n",__func__,__LINE__, tTM->tm_year+1900,tTM->tm_mon+1, tTM->tm_mday,tTM->tm_hour,tTM->tm_min,tTM->tm_sec);
崩溃发生在调用localtime(&curr)时,日志如下:
I app: [getClearAttackStamp][188]:curr = 1705985618. F libc : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x86668f9 in tid 8695 (testserver), pid 8695 (testserver) I crash_dump32: obtaining output fd from tombstoned, type: kDebuggerdTombstone I /system/bin/tombstoned: received crash request for pid 8695 I crash_dump32: performing dump of process 8695 (target tid = 8695) F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** F DEBUG : Build fingerprint: /QKQ1.200407.002/eng.builde.20240117.171303:userdebug/test-keys' F DEBUG : Revision: '0' F DEBUG : ABI: 'arm' F DEBUG : Timestamp: 2024-01-23 12:53:38+0800 F DEBUG : pid: 8695, tid: 8695, name: lifecycleserver >>> /product/bin/testserver<<< F DEBUG : uid: 1000 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x86668f9 F DEBUG : r0 b0e2826b r1 086668f9 r2 b0ec81a0 r3 b0e2826d F DEBUG : r4 b0ec8208 r5 bec4f16c r6 b0ec6a74 r7 bec4f1a8 F DEBUG : r8 bec4f170 r9 b0ec8260 r10 00000000 r11 8103145b F DEBUG : ip 00000002 sp bec4f0a8 lr bec5168c pc b0ea76f0 F DEBUG : F DEBUG : backtrace: F DEBUG : #00 pc 0009b6f0 /apex/com.android.runtime/lib/bionic/libc.so (getenv+48) F DEBUG : #01 pc 000a23ff /apex/com.android.runtime/lib/bionic/libc.so (tzset_unlocked+18) F DEBUG : #02 pc 0009e2fd /apex/com.android.runtime/lib/bionic/libc.so (localtime+28) (BuildId: ) F DEBUG : #03 pc 00007153 /product/bin/testserver F DEBUG : #04 pc 00006f8b /product/bin/testserver F DEBUG : #05 pc 00006075 /product/bin/testserver
怀疑是时区环境问题,但不确定具体原因,寻求解决办法。
分析与解决方案
从崩溃栈可见,崩溃根源是getenv函数访问非法内存,而getenv由tzset_unlocked调用,最终触发localtime崩溃。结合仅首次烧录镜像出现、重启后正常的现象,核心原因是首次开机时系统时区环境变量尚未初始化完成,导致libc内部处理时区时出现内存访问错误。
具体解决方法:
延迟调用时间相关函数:
首次开机时,等待系统完成初始化(比如监听系统广播ACTION_BOOT_COMPLETED)后再执行localtime等时间函数,避免在系统环境未就绪时调用。替换为线程安全的函数:
用localtime_r替代localtime,这是线程安全版本,不依赖全局时区缓存,还能避免空指针风险:time_t curr; struct tm tTM = {0}; // 栈上分配结构体,避免指针空引用 char pcurDate[24] = {0}; time(&curr); LOG_I("[getClearAttackStamp][%d]:curr = %ld.\r\n",__LINE__,curr); localtime_r(&curr, &tTM); // 使用线程安全版本 LOG_I("[%s][%d]: %4d-%02d-%02d %02d:%02d:%02d.\r\n",__func__,__LINE__, tTM.tm_year+1900,tTM.tm_mon+1, tTM.tm_mday,tTM.tm_hour,tTM.tm_min,tTM.tm_sec);主动初始化时区环境(备选):
在调用localtime前手动调用tzset()初始化时区,但该方法依然依赖环境变量,首次开机时可能仍有问题,优先推荐前两种方案。
内容的提问来源于stack exchange,提问作者prop
相关产品推荐
相关产品推荐

