[PATCH] with cmd:parallel>1 and cmd:fail-exit true only the first command will be executed

Fernando Gutierrez <[email protected]> Wed, 1 Jun 2011 18:57:47 +0200
Newsgroups gmane.network.lftp.devel
Message-ID <[email protected]>
--bcaec52160bfb8687204a4a96c24
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

**Problem:
With cmd:parallel=3D1 it works fine because CmdExec::Do() waits (returns
early) until the running job is finished before spawning the next one
in exec_parsed_command(). When it finishes, the exit code of that job
is stored in exit_code, that exec_parsed_command() will check (when
cmd:fail-exit=3Dtrue) in order to see if it must end the program
(removing the feeder and emptying the buffer).

However when you have several in parallel, if CMD(something) doesn't
set exit_code=3D0, the next time exec_parsed_command() is called (that
is, the next command in the buffer) will think there was an error and
will prevent the rest of the commands from executing.

exit_code is set to 1 in exec_parsed_command() before making the new
job (new_job=3Dc->creator(this);) =C2=A0creator(this) calls a CMD(something=
)
in commands.cc and that will sometimes set exit_code=3D0 when it
finishes successfully, or ignore it (exit_code being 1)


**Tests:

.lftp/rc:
set cmd:fail-exit true;
set cmd:parallel 2;

lftp -f file:

-First example

file:
open fish://user:pass@ip;
chmod 755 a;
chmod 755 a;

chmod will only be executed once

-Second example

file:
get -c http://file1;
get -c http://file2;

Only file1 will be downloaded.

**Fix:

exit_code must be 0, or the fail-exit check must be changed to only
run if a job just finished, which isn't easy because some commands
don't make new jobs, the finish and just leave exit_code=3D1.

After making a new job, if a new object has actually been created,
AddNewJob is called. If the command is in the background, it is
executed and if not finished, suspended (put in the background) with
SuspendJob. The interesting part is that function also sets
exit_code=3D0.

When a job finishes, its status code is stored in exit_code. I've
tried to find if that wasn't always the case, but it seems all
external and built-in commands do it. So exit_code=3D1 shouldn't be
necessary while the jobs are running. I thought maybe it was made that
way because a job could somehow finish in an error state and bypassing
the place where its status code is put into exit_code, but I didn't
find any of such cases.

Also, because you can background a job whenever you want, that means
the exit_code of its CmdExec can be changed to 0 at any moment,
telling me it's value is not important.

If a job is not created in exec_parsed_command(), then the exit_code
is relevant, because that means the command has already been executed
and exit_code is storing a real value. However, if there is a new job,
it is supposed to exit and give a code. So, would the proper fix be
adding exit_code=3D0 to AddNewJob? it works, and that's what I
implemented.

--bcaec52160bfb8687204a4a96c24
Content-Type: application/octet-stream; name="fail-exit.patch"
Content-Disposition: attachment; filename="fail-exit.patch"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_go4kq8z80

LS0tIG9yaWcvQ21kRXhlYy5jYwkyMDExLTA0LTI5IDA2OjU4OjI3LjAwMDAwMDAwMCArMDIwMAor
KysgcGF0Y2hlZF9sZnRwLTQuMi4zL3NyYy9DbWRFeGVjLmNjCTIwMTEtMDUtMjQgMDk6NTI6MzQu
MDAwMDAwMDAwICswMjAwCkBAIC0yNTEsNiArMjUxLDcgQEAKICAgIGlmKG5ld19qb2ItPmpvYm5v
PDApCiAgICAgICBuZXdfam9iLT5BbGxvY0pvYm5vKCk7CiAgICBuZXdfam9iLT5TZXRQYXJlbnRG
Zyh0aGlzLCFiYWNrZ3JvdW5kKTsKKyAgIGV4aXRfY29kZT0wOwogICAgQWRkV2FpdGluZyhuZXdf
am9iKTsKICAgIGlmKGJhY2tncm91bmQpIHsKICAgICAgIFJvbGwobmV3X2pvYik7Cg==
--bcaec52160bfb8687204a4a96c24--