Do Android init property triggers always happen on boot and if so when exactly? - android-source

Documentation from Google on Android init at https://android.googlesource.com/platform/system/core/+/oreo-release/init/README.md says the following
An Action can have multiple property triggers but may only have one
event trigger.
For example: on boot && property:a=b defines an action that is only
executed when the ‘boot’ event trigger happens and the property a
equals b.
on property:a=b && property:c=d defines an action that is executed
at three times:
During initial boot if property a=b and property c=d.
Any time that property a transitions to value b, while property c already equals d.
Any time that property c transitions to value d, while property a already equals b.
In the first example the on boot trigger seems to be a necessary condition for the action to be executed at boot. However in the second example no on boot trigger is used yet the documentation says the action will still be executed on boot anyway.
So it seems only one of two statements is true:
property triggers never happen at boot automatically in which case the second example description is wrong about case #1
property triggers are always executed at boot when they are true and not only when they transition, in that case the first example need not include the boot trigger.
If the second statement is true then is it specifically the boot phase and not say late-init?

I decided to just go ahead and run some tests. The evidence shows that the documentation is correct about what happens but lacking in detail as to why.
The first example on boot && property:a=b will execute during boot when init fires boot event. Note that not all properties are initialized at the same time and as such this may affect their availability during the various boot events. Also note that this example won't run when the property changes. The main confusion is that properties in init are both events and states, where as the init phases are only events.
The second example runs during boot, but it is not related to the boot event! It runs when init enables property triggers (see below for details). Also as described it runs when either property changes to the declared value and the other property condition is true.
Test results:
on boot
exec /system/bin/echo "Trigger test A"
Run when init script triggers boot event
on late-init
exec /system/bin/echo "Trigger test B"
Run when init triggers late-init event
on property:persist.testing=1
exec /system/bin/echo "Trigger test C"
Run when property is loaded from filesystem persisted properties (at time of test this was after post-fs-data completed), this also runs when property transitions to the specified value any time later
on boot && property:persist.testing=1
exec /system/bin/echo "Trigger test D"
Never run, persist properties are not available when boot is triggered
on post-fs-data && property:persist.testing=1
exec /system/bin/echo "Trigger test E"
Never run, persist property is not available when post-fs-data is triggered, it is available immediately afterwards but that's too late!
on property:ro.build.type=eng
exec /system/bin/echo "Trigger test F"
Run when property triggers are enabled, after late-init has finished being triggered (see note below on why)
on boot && property:ro.build.type=eng
exec /system/bin/echo "Trigger test G"
Run during boot process when init triggers boot event, the property was available at that time
on post-fs-data && property:ro.build.type=eng
exec /system/bin/echo "Trigger test H"
Run during boot process twice when init triggers post-fs-data event, once when data is mounted prior to decryption and once when data is mounted after decryption
on late-init && property:ro.build.type=eng
exec /system/bin/echo "Trigger test I"
Run when init triggers late-init
Historical evidence:
01-25 23:26:25.605 0 0 W : Trigger test B
01-25 23:26:25.605 0 0 W : Trigger test I
01-25 23:26:26.892 0 0 W : Trigger test H
01-25 23:26:28.475 0 0 I init : processing action (early-boot) from (/vendor/etc/init/hw/init.target.rc:79)
01-25 23:26:28.537 0 0 I init : processing action (boot) from (/init.rc:660)
01-25 23:26:28.745 0 0 I : Trigger test A
01-25 23:26:28.778 0 0 I : Trigger test G
01-25 23:26:28.939 0 0 I : Trigger test F
01-25 23:26:31.070 0 0 I : Trigger test H
01-25 23:26:34.871 0 0 I init : processing action (post-fs-data) from (/system/etc/init/bootstat.rc:9)
01-25 15:26:35.284 0 0 I : Trigger test C
01-25 15:26:42.468 0 0 I init : processing action (sys.boot_completed=1) from (/init.rc:819)
UPDATE 2022:
I updated some of the prior explanations and test results.
It was pointed out that property-only triggers happen after late-init. Unclear why Google chose to do that but looking at init.cpp you can see the following code in init.cpp:
// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = GetProperty("ro.bootmode", "");
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");
}
// Run all property triggers based on current state of the properties.
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
This means all late-init and earlier triggers run before property-only triggers. So a trigger such as on late-init && property:xyz=* runs before the trigger on property:xyz=*!

Related

Restart Application Service with install4j

Is it possible to restart a Java application Service with install4j ?
I need to change some configurations in the application and then restart it in unattended mode using the api. (Not doing the complete install or update)
I found this answer that would work if the application is not a service: https://stackoverflow.com/a/65777281/150566
I tried to do the same thing using a Custom Application but using Service call like this:
I've also tried without the request privileges and without sleep with same result or using the stop service commandHalf of it works. The service stops but the Service never restart.
Is there something missing so that the service can start again ? Is there other alternative ?
Updated info:
The config is changed as mentioned to stop the service instead of ShutDown calling launcher:
When using debug as mentioned by Ingo Kegel those output are the result:
Called from mylauncher Service with the Api (not working):
[INFO] com.install4j.runtime.beans.actions.services.StopServiceAction [ID 147]: Execute action
Property executable: null
Property launcherId: 36
Property serviceName: null
Property windowsStopMinimumWaitTime: 30000
Property rollbackSupported: true
usedExecutable: C:\MyInstaller\mylauncher.exe
Stop minimum wait time: 30000
Called from command line (working):
[INFO] com.install4j.runtime.beans.actions.services.StopServiceAction [ID 147]: Execute action
Property executable: null
Property launcherId: 36
Property serviceName: null
Property windowsStopMinimumWaitTime: 30000
Property rollbackSupported: true
usedExecutable: C:\MyInstaller\mylauncher.exe
Stop minimum wait time: 30000
previous state true
Execute action successful after 519 ms
[INFO] com.install4j.runtime.beans.actions.services.StartServiceAction [ID 148]: Execute action
Property executable: null
Property launcherId: 36
Property serviceName: null
Property autostartOnly: false
Property rollbackSupported: true
usedExecutable: C:\MyInstaller\mylauncher.exe
previous state false
Execute action successful after 44 ms
[INFO] com.install4j.runtime.beans.screens.StartupScreen [ID 131]: command: move 1 screens, executing actions, checking condition
[INFO] cleaning up
[INFO] Finished at 2023-02-06 15:06:06
(I've also tried without the request privileges and without sleep with same result or using the stop service command)
Instead of "Shutdown calling launcher" you need the "Stop a service" action. Also, for unattended mode, you don't need the "Finish" screen, you can add all actions to the "Startup" node.
To check if there is a problem, start the executable of the custom application from the command line with the argument -Dinstall4j.log=<path to writable log file.txt> and check the log file.

Azure DevOps, When a job in the stage is successful, how can it be ensured that stage is successful or partially successful?

When one of the jobs in the stage is successful and the other is fail, how can it be ensured that that stage is successful and proceeds to the next stage?
If I'm more descriptive,
Pipeline
A(Stage) --> B(Stage)
-Job1(failed) -Job1
- ...
-Job2(succeeded)
(run only when previous job failed)
When Job 1 in A stage is fail, automatically Job 2 running. But in this way, stage A is resulted 'Failed'. Therefore, Stage B is never running because of previous stage failed.
"Trigger even when the selected stages partially succeed" button is not working for stage B because previous stage marked as "fail".
Additionally, I tried:
If i mark all tasks inside "A -> Job1" as "Continue on error" and i checked "Trigger even when the selected stages partially succeed" box in stage B this time "Job 2" not running because "run only when previous job failed " option marked on job 2. There is no option like "run only when previous job partially succeeded".
In addition, custom condition not working in Job 2, its show null for "Agent.JobStatus" variable. If these "SucceededWithIssues" and "Failed" status available for "Agent.JobStatus" it can be run but I couldn't come to a conclusion here because null value of JobStatus.

Spring Batch Job Stop Using jobOperator

I have Started my job using jobLauncher.run(processJob,jobParameters); and when i try stop job using another request jobOperator.stop(jobExecution.getId()); then get exeption :
org.springframework.batch.core.launch.JobExecutionNotRunningException:
JobExecution must be running so that it can be stopped
Set<JobExecution> jobExecutionsSet= jobExplorer.findRunningJobExecutions("processJob");
for (JobExecution jobExecution:jobExecutionsSet) {
System.err.println("job status : "+ jobExecution.getStatus());
if (jobExecution.getStatus()== BatchStatus.STARTED|| jobExecution.getStatus()== BatchStatus.STARTING || jobExecution.getStatus()== BatchStatus.STOPPING){
jobOperator.stop(jobExecution.getId());
System.out.println("###########Stopped#########");
}
}
when print job status always get job status : STOPPING but batch job is running
its web app, first upload some CSV file and start some operation using spring batch and during this execution if user need stop then stop request from another controller method come and try to stop running job
Please help me for stop running job
If you stop a job while it is running (typically in a STARTED state), you should not get this exception. If you have this exception, it means you have stopped your job while it is currently stopping (that is what the STOPPING status means).
jobExplorer.findRunningJobExecutions returns only running executions, so if in the next line right after this one you have a job in STOPPING status, this means the status changed right after calling jobExplorer.findRunningJobExecutions. You need to be aware that this is possible and your controller should handle this case.
When you tell spring batch to stop a job it goes into STOPPING mode. What this means is it will attempt to complete the unit of work chunk it is currently processing but then stop working. Likely what's happening is you are working on a long running task that is not finishing a unit of work (is it hung?) so it can't move from STOPPING to STOPPED.
Doing it twice rightly leads to an Exception because your job is already STOPPING by the time you did it the first time.

How spring batch admin is stopping a running job?

How spring batch admin is stopping a running job from the UI .
On the spring batch admin's online documentation i have read the following lines .
"A job that is executing can be stopped by the user (whether or not it
is launchable). The stop signal is sent via the database and once
detected by Spring Batch in whatever process is running the job, the
job is stopped (status moves from STOPPING to STOPPED) and no further
processing takes place."
Does that mean Spring batch admin UI is directly changing the status of job inside the spring batch table ?
UPDATE: I tried executing the below query on the running job .
update batch_job_execution set status="STOPPED" where job_ins
tance_id=19;
The above query is getting updated in the DB but spring batch is not bale to stop the running job.
If anybody has tried this please do share the logic here .
You're confused between Batch Status vs. Exit Status.
What are you doing with that SQL is changed the STATUS to STOPPED
When a job is running you can stop the job from the code. In each step iteration, check their status and if STOPPING its set, then send the step to stop ongoing.
Anyway, what you doing is not elegant. The correct way is explained in Common Batch Patterns -> 11.2 Stopping a Job Manually for Business Reasons
public class FooProcessor implements ItemProcessor<FooIn,FooOut>{
public FooOut process(FooIn foo) throws Exception {
if (sendToStop(item)) {
throw new MyStopException("I need to Stop: " + item);
}
//do my stuff
return new FooOut(foo);
}
}
Another simple way to stop chunk step is return null in the reader. This tells us that no more elements to iterate the reader
public T read() throws Exception {
T item = delegate.read();
if (ifNeedStop(item)) {
return null; // end the step here
}
return item;
}
I investigated the spring batch code.
It seems they update both the version and status of the BATCH_JOB_EXECUTION.
This works for me:
update batch_job_execution set status="STOPPED", version=version+1 where job_instance_id=19;
If you look into the jars of spring batch admin, you can see that in AbstractStep.java(spring-batch admin class) it checks for the status of the Step and Job from Database .
Based on this status it validates step before running it .
This works well for all cases except in chunk, since next step is called after large processing . If you want to implement in it, you can implement your own listener to check status (but it will increase DB hits) .

Buildbot slaves priority

Problem
I have set up a latent slave in buildbot to help avoid congestion.
I've set up my builds to run either in permanent slave or latent one. The idea is the latent slave is waken up only when needed but the result is that buildbot randomly selectes one slave or the other so sometimes I have to wait for the latent slave to wake even if the permanent one is idle.
Is there a way to prioritize buildbot slaves?
Attempted solutions
1. Custom nextSlave
Following #david-dean suggestion, I've created a nextSlave function as follows (updated to working version):
from twisted.python import log
import traceback
def slave_selector(builder, builders):
try:
host = None
support = None
for builder in builders:
if builder.slave.slavename == 'host-slave':
host = builder
elif builder.slave.slavename == 'support-slave':
support = builder
if host and support and len(support.slave.slave_status.runningBuilds) < len(host.slave.slave_status.runningBuilds):
log.msg('host-slave has many running builds, launching build in support-slave')
return support
if not support:
log.msg('no support slave found, launching build in host-slave')
elif not host:
log.msg('no host slave found, launching build in support-slave')
return support
else:
log.msg('launching build in host-slave')
return host
except Exception as e:
log.err(str(e))
log.err(traceback.format_exc())
log.msg('Selecting random slave')
return random.choice(buildslaves)
And then passed it to BuilderConfig.
The result is that I get this in twistd.log:
2014-04-28 11:01:45+0200 [-] added buildset 4329 to database
But the build never starts, in the web UI it always appear as Pending and none of the logs I've put appear in twistd.log
2. Trying to mimic default behavior
I've having a look to buildbot code, to see how it is done by default.
in file ./master/buildbot/process/buildrequestdistributor.py, class BasicBuildChooser you have:
self.nextSlave = self.bldr.config.nextSlave
if not self.nextSlave:
self.nextSlave = lambda _,slaves: random.choice(slaves) if slaves else None
So I've set exactly that lambda function in my BuilderConfig and I'm getting exactly the same build not starting result.
You can set up a nextSlave function to assign slaves to a builder in a custom manner see: http://docs.buildbot.net/current/manual/cfg-builders.html#builder-configuration