ybc3066978 / roottools

Automatically exported from code.google.com/p/roottools
0 stars 0 forks source link

Proper way to wait for the command to end #52

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago

What version of the product are you using? On what operating system?
RootTools 3.3 

Please provide any additional information below.

Im trying to execute a command but i have to wait till it finishes since i need 
the output bu no matter what i do i can get it to work, ive tried the function 
posted on a closed issue but doesnt seem to work

function posted on the other issue:
private static void commandWait(Command cmd) throws Exception {

        while (!cmd.isFinished()) {

            synchronized (cmd) {
                try {
                    if (!cmd.isFinished()) {
                        cmd.wait(2000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

my code:

final ArrayList<String> output = new ArrayList<String>();
        Command command = new Command(0, "cat /proc/version"){
            @Override
            public void commandCompleted(int id, int exitCode) {
                // TODO Auto-generated method stub
                Log.d("DKM.Commands.Completed", output.toString());

            }

            @Override
            public void commandOutput(int id, String line) {
                // TODO Auto-generated method stub
                output.add(line);

            }

            @Override
            public void commandTerminated(int id, String reason) {
                // TODO Auto-generated method stub

            }

        };
        try {
            commandWait(RootTools.getShell(false).add(command));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TimeoutException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (RootDeniedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Log.d("DKM.Commands.AfterWait", output.toString());

This is the log:

10-18 14:29:07.730: D/DKM.Commands(4084): cat /proc/version
10-18 14:29:07.860: D/DKM.Commands.AfterWait(4084): []
10-18 14:29:08.179: D/DKM.Commands.Completed(4084): [, , , Linux version 
2.6.29-g46b05b2 (vchtchetkine@vc-irv.irv.corp.google.com) (gcc version 4.4.3 
(GCC) ) #28 Thu Nov 17 06:39:36 PST 2011, , ]

doesnt seem to wait till it finishes :(

Original issue reported on code.google.com by bradleyr...@gmail.com on 18 Oct 2013 at 8:29

GoogleCodeExporter commented 9 years ago
You need to do the following:

RootTools.getShell(false).add(command);
commandWait(command);

Original comment by Stericso...@gmail.com on 28 Oct 2013 at 3:57

GoogleCodeExporter commented 9 years ago
Still the same 

11-04 12:07:54.052: D/DKM.Commands.AfterWait(603): []
11-04 12:07:55.274: D/DKM.Commands.Completed(603): [, Linux version 
2.6.29-g46b05b2 (vchtchetkine@vc-irv.irv.corp.google.com) (gcc version 4.4.3 
(GCC) ) #28 Thu Nov 17 06:39:36 PST 2011, , ]

Original comment by bradleyr...@gmail.com on 4 Nov 2013 at 6:10

GoogleCodeExporter commented 9 years ago
I think I see what you are saying. You want the completed callback to be 
executed before the wait is completed?

At the time that the lock releases the command is technically completed but the 
actual callback is executed after the lock is released. If you want to wait 
until you do something after the command completes then you should handle that 
in a different manner.

The library doesn't technically care what you do with the callback methods, and 
I don't think that it really should. With that being said, the library calls 
the callbacks and moves on. If you need to defer your execution based on 
something you are doing in a callback then you'll need to create you lock on 
something other than the cmd.isFinished property.

To be honest it sounds like you need to break out the functionality you want 
deferred into a separate method and have it called once you are done with the 
commandFinished callback.

Original comment by Stericso...@gmail.com on 4 Nov 2013 at 6:26

GoogleCodeExporter commented 9 years ago
i know what you are saying but the whole idea of the wait is to get the output 
of the command and do something with it

the commandCompleted callback is just there to see that my output is not empty 
it does nothing really what bothers me is that the output is empty after the 
wait

Original comment by bradleyr...@gmail.com on 4 Nov 2013 at 6:53

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
yeh thats the output from the commandCompleted callback
the output after the wait is empty

Log.d("DKM.Commands.AfterWait", output.toString());

11-04 12:07:54.052: D/DKM.Commands.AfterWait(603): []

Original comment by bradleyr...@gmail.com on 4 Nov 2013 at 7:00

GoogleCodeExporter commented 9 years ago
Ok, so a few things....

If you are doing this from the main thread then a handler is being used to call 
your callback methods on the thread that you executed the command from. There 
can be a delay from the time this message is sent to the time that the callback 
method is executed on your thread (Not something I can control)

This is probably why you are seeing this issue, the execution of your callback 
methods are happening AFTER the lock has been released because of the delay in 
execution of your callback methods. If you are not doing UI work then you can 
do the following to disable the use of the handler:

RootTools.handlerEnabled = false (disables the handler for the entire library)

or 

new Command(0, false, "cat /proc/version") (disables the handler just for this 
command)

This will result in the callback methods being executed in a different thread 
than the one you executed the command from but will result in the callback 
methods being executed immediately)

The other way to go about handling this would be to remove the lock and perform 
the next block of functionality when the commandCompleted method is called.

Original comment by Stericso...@gmail.com on 4 Nov 2013 at 7:10

GoogleCodeExporter commented 9 years ago
Disabling the handler for the command did it!  thanks for the help :)

Original comment by bradleyr...@gmail.com on 4 Nov 2013 at 7:18

GoogleCodeExporter commented 9 years ago
Sure, just one last thing...you really should not be executing commands from 
the main UI thread. 

Put your command execution inside of a thread (use AsyncTask). By default the 
handler will be disabled as long as you don't have a looper object associated 
with your thread.

Also, holding a lock can cause your application to throw an ANR and your users 
are really not going to like that and debugging those issues are a pain so if 
you can try to design your application so that you don't have to rely on locks.

Just my two cents :)

Original comment by Stericso...@gmail.com on 4 Nov 2013 at 7:26