syncthing / syncthing-android

Wrapper of syncthing for Android.
https://syncthing.net/
Mozilla Public License 2.0
3.47k stars 390 forks source link

Can't create handler inside thread that has not called Looper.prepare() #18

Closed pysiak closed 10 years ago

pysiak commented 10 years ago

I think home dir bug is gone but I am getting this one upon startup. Handler.java:121

Got my stack traces?

Nutomic commented 10 years ago

Yeah I got it. Gingerbread really doesnt like syncthing D:

java.lang.ExceptionInInitializerError
at com.nutomic.syncthingandroid.syncthing.SyncthingService$1.run(SyncthingService.java:253)
at java.lang.Thread.run(Thread.java:1019)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
... 2 more

Here's a fixed build (hopefully). Could you try if it works, and post a new logcat if not?

Edit: That build won't actually work, will post a new one.

Edit 2: Updated the above link.

pysiak commented 10 years ago

Removed the playstore app and installed from apk. After the welcome message about alpha status it crashes without allowing to send report or view stack trace. Just says stopped unexpectedly.

Nutomic commented 10 years ago

Yeah reporting only works when installing through play store.

Can you make a logcat of the crash (see google), and post that?

chr15m commented 10 years ago

Hello! Sorry for creating a new issue #28 - I should have checked that first. I tried the apk posted above and I get the following crash, but this time it gets to the welcome message before crashing:

I/ActivityManager( 1298): Starting: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=com.nutomic.syncthingandroid.debug/com.nutomic.syncthingandroid.WebGuiActivity } from pid 10775 I/ActivityManager( 1298): Start proc com.nutomic.syncthingandroid.debug for activity com.nutomic.syncthingandroid.debug/com.nutomic.syncthingandroid.WebGuiActivity: pid=10835 uid=10126 gids={1015, 3003} I/SyncthingService(10835): App started for the first time. Copying default config, keys will be generated automatically I/SyncthingService(10835): Checking for needed config updates I/com.dattasmoon.pebble.plugin( 1471): Event: android.view.accessibility.AccessibilityEvent@4052d798; EventType: 64; EventTime: 47222886; ClassName: android.app.Notification; PackageName: com.nutomic.syncthingandroid.debug; Text: []; ContentDescription: null; ItemCount: 0; CurrentItemIndex: -1; IsEnabled: false; IsPassword: false; IsChecked: false; IsFullScreen: false; BeforeText: null; FromIndex: 0; AddedCount: 0; RemovedCount: 0; ParcelableData: Notification(vibrate=null,sound=null,defaults=0x0,flags=0x62) I/ActivityManager( 1298): Displayed com.nutomic.syncthingandroid.debug/com.nutomic.syncthingandroid.WebGuiActivity: +2s970ms I/SyncthingService(10835): Web GUI will be available at http://127.0.0.1:8080 D/PackageBroadcastService( 1793): Received broadcast action=android.intent.action.PACKAGE_ADDED and uri=com.nutomic.syncthingandroid.debug D/dalvikvm(10867): DexOpt: couldn't find static field W/dalvikvm(10867): VFY: unable to resolve static field 85 (BLOCKED) in Landroid/net/NetworkInfo$DetailedState; D/dalvikvm(10867): VFY: replacing opcode 0x62 at 0x0024 D/dalvikvm(10867): VFY: dead code 0x0026-0029 in Lcom/google/android/finsky/utils/Utils;.isBackgroundDataEnabled (Landroid/content/Context;)Z I/SyncthingService(10835): stdout: I/SyncthingService(10835): stdout: I/SyncthingService(10835): stdout: 07:57:34 FATAL: No home directory found - set $HOME (or the platform equivalent). I/SyncthingService(10835): stdout: W/dalvikvm(10835): threadid=11: thread exiting with uncaught exception (group=0x4001d570) I/dalvikvm(10867): Could not find method android.net.TrafficStats.setThreadStatsTag, referenced from method com.android.volley.NetworkDispatcher.addTrafficStatsTag W/dalvikvm(10867): VFY: unable to resolve static method 658: Landroid/net/TrafficStats;.setThreadStatsTag (I)V D/dalvikvm(10867): VFY: replacing opcode 0x71 at 0x000a E/AndroidRuntime(10835): FATAL EXCEPTION: Thread-12 E/AndroidRuntime(10835): com.nutomic.syncthingandroid.syncthing.SyncthingService$NativeExecutionException: Syncthing binary returned error code 3 E/AndroidRuntime(10835): stdout: E/AndroidRuntime(10835): stdout: E/AndroidRuntime(10835): stdout: 07:57:34 FATAL: No home directory found - set $HOME (or the platform equivalent). E/AndroidRuntime(10835): stdout: E/AndroidRuntime(10835): E/AndroidRuntime(10835): at com.nutomic.syncthingandroid.syncthing.SyncthingService.runNative(SyncthingService.java:163) E/AndroidRuntime(10835): at com.nutomic.syncthingandroid.syncthing.SyncthingService.access$700(SyncthingService.java:49) E/AndroidRuntime(10835): at com.nutomic.syncthingandroid.syncthing.SyncthingService$1.run(SyncthingService.java:270) E/AndroidRuntime(10835): at java.lang.Thread.run(Thread.java:1019) W/ActivityManager( 1298): Force finishing activity com.nutomic.syncthingandroid.debug/com.nutomic.syncthingandroid.WebGuiActivity E/WindowManager(10835): Activity com.nutomic.syncthingandroid.WebGuiActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@4054ea30 that was originally added here E/WindowManager(10835): android.view.WindowLeaked: Activity com.nutomic.syncthingandroid.WebGuiActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@4054ea30 that was originally added here E/WindowManager(10835): at android.view.ViewRoot.(ViewRoot.java:258) E/WindowManager(10835): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148) E/WindowManager(10835): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) E/WindowManager(10835): at android.view.Window$LocalWindowManager.addView(Window.java:424) E/WindowManager(10835): at android.app.Dialog.show(Dialog.java:241) E/WindowManager(10835): at android.app.AlertDialog$Builder.show(AlertDialog.java:802) E/WindowManager(10835): at com.nutomic.syncthingandroid.WebGuiActivity.onCreate(WebGuiActivity.java:83) E/WindowManager(10835): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) E/WindowManager(10835): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611) E/WindowManager(10835): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663) E/WindowManager(10835): at android.app.ActivityThread.access$1500(ActivityThread.java:117) E/WindowManager(10835): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931) E/WindowManager(10835): at android.os.Handler.dispatchMessage(Handler.java:99) E/WindowManager(10835): at android.os.Looper.loop(Looper.java:130) E/WindowManager(10835): at android.app.ActivityThread.main(ActivityThread.java:3683) E/WindowManager(10835): at java.lang.reflect.Method.invokeNative(Native Method) E/WindowManager(10835): at java.lang.reflect.Method.invoke(Method.java:507) E/WindowManager(10835): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) E/WindowManager(10835): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) E/WindowManager(10835): at dalvik.system.NativeStart.main(Native Method) I/SyncthingService(10835): Shutting down service I/PostTask(10835): Sending POST request to http://127.0.0.1:8080/rest/shutdown W/PostTask(10835): Failed to call Rest API at http://127.0.0.1:8080/rest/shutdown W/PostTask(10835): org.apache.http.conn.HttpHostConnectException: Connection to http://127.0.0.1:8080 refused W/PostTask(10835): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:178) W/PostTask(10835): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) W/PostTask(10835): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) W/PostTask(10835): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:359) W/PostTask(10835): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) W/PostTask(10835): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) W/PostTask(10835): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) W/PostTask(10835): at com.nutomic.syncthingandroid.syncthing.PostTask.doInBackground(PostTask.java:30) W/PostTask(10835): at com.nutomic.syncthingandroid.syncthing.PostTask.doInBackground(PostTask.java:16) W/PostTask(10835): at android.os.AsyncTask$2.call(AsyncTask.java:185) W/PostTask(10835): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) W/PostTask(10835): at java.util.concurrent.FutureTask.run(FutureTask.java:138) W/PostTask(10835): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) W/PostTask(10835): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) W/PostTask(10835): at java.lang.Thread.run(Thread.java:1019) W/PostTask(10835): Caused by: java.net.ConnectException: /127.0.0.1:8080 - Connection refused W/PostTask(10835): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:207) W/PostTask(10835): at org.apache.harmony.luni.net.PlainSocketImpl.connect(PlainSocketImpl.java:437) W/PostTask(10835): at java.net.Socket.connect(Socket.java:983) W/PostTask(10835): at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119) W/PostTask(10835): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:143) W/PostTask(10835): ... 14 more

I had to cherry pick these lines out - if there's some grep/filter to apply that would help, let me know.

Nutomic commented 10 years ago

That's weird, it can't read environment variables properly (07:57:34 FATAL: No home directory found - set $HOME (or the platform equivalent).).

Can you try what the output of MYVAR=123 and then echo $MYVAR is in the shell?

chr15m commented 10 years ago

That works fine. I think the issue is that $HOME isn't set on my platform. When I run export there is no HOME in the list.

chr15m commented 10 years ago

$EXTERNAL_STORAGE is set to /mnt/sdcard - maybe it could set $HOME to that in the event it is not set already?

Nutomic commented 10 years ago

I run HOME=/data/data/com.nutomic.syncthingandroid/ before executing the binary, so it should be set.

It's really hard debugging something without any way to reproduce/play around with it. I think it would be helpful if someone with a Gingerbread device could set up a build (see the readme) and figure out what the problem is, exactly.

Edit: Btw I was sure I fixed the HOME dir problem in 0.3.2 (by setting HOME to the above path instead of /sdcard/), not sure why that reappears for you.

chr15m commented 10 years ago

I will set up a build.

Nutomic commented 10 years ago

Great, thank you :)

chr15m commented 10 years ago

I have it building now but I am getting the "Can't create handler inside thread that has not called Looper.prepare()" crash - how did you prevent that in the build you released above?

chr15m commented 10 years ago

By the way, the way you have set the HOME variable won't let it be available to the syncthing process. You have done it like this in the shell:

HOME=X...
./syncthing # <- can't see $HOME

You need to do this instead:

HOME=X/x/x ./syncthing

Note the space instead of the carriage return. Then the shell will pass the environment variable to the subprocess. You could probably also use export but the above should work. I will submit a clean patch.

Nutomic commented 10 years ago

I'm surprised that doesn't work on Gingerbread, as it definitely works on ICS+ as well as my Kubuntu desktop.

Btw I fixed the Looper issue by just calling Looper.prepare() in the Runnable, maybe you could try if that works, for a cleaner solution?

chr15m commented 10 years ago

I think it does not work on any unix. Create a file called test.sh as follows:

#!/bin/sh
echo $TEST

chmod it 755.

TEST=4
./test.sh

Then:

TEST=4 ./test.sh

Only the second one yeilds the correct value of 4.

I don't know enough about Android to know if calling Looper.prepare() or running on the UI thread the way my patch did is the cleaner solution. Feel free to merge and modify the patch if you think it needs it.

chr15m commented 10 years ago

On Kubuntu the HOME environment variable would be set correctly already. Probably the same for ICS.

Nutomic commented 10 years ago

No i mean i run TEST=123\n echo $TEST and get "123".

Oh and I didnt call Looper.loop(), just the prepare.

And while you're at it, could you try if setting HOME to sdcard works, and change it to that if so?

chr15m commented 10 years ago

That is because the $TEST is being evaluated in the same process as it was declared and then passed to echo after evaluation. echo is not reading an environment variable in this instance, the shell it is being executed in is. So it works on Gingerbread the way you have written above exactly. What does not work on Kubuntu, ICS, or Gingerbread is declaring the variable on one line and expecting it to be part of a subprocesses environment without exporting it or passing it straight in.

Why don't you commit your code where you have the Looper.prepare() inside the runnable?

I will set HOME to sdcard and test.

Nutomic commented 10 years ago

I wasn't entirely sure if the Looper.prepare() works. If it does, just put it in ;)

chr15m commented 10 years ago

It gives me a permission denied error when trying to chmod if I use Environment.getExternalStorageDirectory() ("/mnt/sdcard") however if I use Environment.getExternalStorageDirectory() + "/syncthing" that works ok. What do you think? Is that an acceptable compromise?

With regards to Looper.prepare() - does that not mean it is still running on a different thread from the GUI? I am not sure how safe that is.

Nutomic commented 10 years ago

The permission error is coming from the syncthing binary? If so, we'll just leave it as it is (HOME could be used as a shortcut for sdcard up to 0.3.2 and I wanted to get that back, but it's really jsut for convenience (and won't be used once I got a proper folder chooser in).

Yes, the idea is that anything that might take long (even though the polling is asynchronous) should be done in a background thread if possible. There weren't any problems with that on ICS+, so if it works on GB, great. Otherwise, we'll use the way you implemented it.

chr15m commented 10 years ago

E/AndroidRuntime( 3342): FATAL EXCEPTION: Thread-11 E/AndroidRuntime( 3342): com.nutomic.syncthingandroid.syncthing.SyncthingService$NativeExecutionException: Syncthing binary returned error code 3 E/AndroidRuntime( 3342): E/AndroidRuntime( 3342): 20:37:53 FATAL: chmod /mnt/sdcard: operation not permitted

I still think that /mnt/sdcard/syncthing is better as a $HOME than HOME=/data/data/com.nutomic.syncthingandroid/ - let me know which you'd prefer and I'll submit the pull request again with the Looper fix too.

Nutomic commented 10 years ago

You're right, /mnt/sdcard/syncthing/ is definitely better if it works. That way people don't accidently sync into the data folder and then wonder why the app takes so much space :D

chr15m commented 10 years ago

Well, I just tried it again and this time I got a permission error trying to chmod /mnt/sdcard/syncthing/ so I have submitted the pull request without that change. Can look at it again tomorrow and will do a new pull request if I get that to work. As of the pull request I just submitted though, it works on Gingerbread with the data directory as HOME without crashing.

Nutomic commented 10 years ago

I'm closing this, feel free to make a pr if you get it working.