Cleaning up old job object in windows - winapi

Scenario
(1) My process has constant JName = "jobName".
(2) Process starts and writes to registry [Key = Pjob, Vlaue = "jobName"], if these values don't already exist. [ This is done so a another process on the machine called R, will periodically look for a job object with the name "jobName", and apply certain job memory limits to this job, if not already done]
(3) Process creates a job object with the name 'jobName',
(4) Process assigns the current process to jobName.
Suppose we start off with process P ,that goes through (1),(2),(3),(4) and then crashes.
The process is woken up by service fabric as P1 and tries to goes through (1) (2) (3) (4)
At (3) , when P1 attempts to create a job object with the name jobName, I believe it is actually getting back the existing handle to the job created by P.
'If the object existed before the function call, the function returns a handle to the existing job object'
At (4) At this point Assigning p1 to the job object fails with the below error
Unhandled exception: System.ComponentModel.Win32Exception (5): Access is denied.
at Win32Wrappers.AssignProcessToJobObject(IntPtr jobHandle, IntPtr processHandle) in \Win32Wrapperscs.cs:line 100
JobObjectUtils.CreateJobObject() in
JobObjectUtils.cs:line 28
at Program.Main(String[] args) in Program.cs:line 98
Question:
How can I clean up the old job object created by P and start with a fresh new one when P1 is running? [ The name of the job object has to remain the same]

According to AssignProcessToJobObject, All processes within a job must run within the same session as the job.
Your existing job object created by P is in session 1 while the process P1 created by a service is in session 0. So, access is denied.
Your service should use CreateProcessAsUser or equivalent to create the process P1.

Related

AnyLogic population cannot enter process -> location of agents missing

I created a model in which transporters should arrive at the same time as a dataset I collected in real-life. But when I run my model, the following Error occurs:
Exception during discrete event execution:
root.<population>[0]:
This agent isn't located in any space
My steps until now:
Create a population with agents of the type of my agents and fill them with the values of my data
create an event which checks every minute for all objects of my population if their arrival time equals the models time
Write a function that enters them into my process and on the road to come to my factory
Therefor every transporter exists already before being entered into my process so that the event can check the condition.
My problem:
When the condition is true and the object should enter my process an error occurs:
Exception during discrete event execution:
root.<population>[0]:
This agent isn't located in any space
Other times when I run the model, this error occurs:
root.mplkws[-1]:
This agent is already defined as agent living in space 'Discrete 2D' and can't have behaviour for space 'Continuous'
I don't understand why they dont have their initial space already. Everything was created in the Main method and I dont know how and where to change the populations agents location
I tried to set the space on the enter block with agent.setSpace(getSpace())but nothing changed.

Setting global properties in Composed Task which would be accessible in each of subtasks

Setting 'common' properties for child tasks is not working
The SCDF version I'm using is 2.9.6.
I want to make CTR A-B-C, each of tasks does follows:
A : sql select on some source DB
B : process DB data that A got
C : sql insert on some target DB
Simplest way to make this work seems to define shared work directory folder Path "some_work_directory", and pass it as application properties to A, B, C. Under {some_work_directory}, I just store each of task result as file, like select.result, process.result, insert.result, and access them consequently. If there is no precedent data, I could assume something went wrong, and make tasks exit with 1.
================
I tried with a composed task instance QWER, with two task from same application "global" named as A, B. This simple application prints out test.value application property to console, which is "test" in default when no other properties given.
If I tried to set test.value in global tab on SCDF launch builder, it is interpreted as app.*.test.value in composed task's log. However, SCDF logs on child task A, B does not catch this configuration from parent. Both of them fail to resolve input given at launch time.
If I tried to set test.value as row in launch builder, and pass any value to A, B like I did when task is not composed one, this even fails. I know this is not 'global' that I need, it seems that CTR is not working correctly with SCDF launch builder.
The only workaround I found is manually setting app.QWER.A.test.value=AAAAA and app.QWER.B.test.value=BBBBB in launch freetext. This way, input is converted to app.QWER-A.app.global4.test.value=AAAAA, app.QWER-B.app.global4.test.value=BBBBB, and print well.
I understand that, by this way, I could set detailed configurations for each of child task at launch time. However, If I just want to set some 'global' that tasks in one CTR instance would share, there seems to be no feasible way.
Am I missing something? Thanks for any information in advance.
CTR will orchestrate the execution of a collection of tasks. There is no implicit data transfer between tasks. If you want the data from A to be the input to B and then output of B becomes the input of C you can create one Task / Batch application that have readers and writers connected by a processor OR you can create a stream application for B and use JDBC source and sink for A and C.

Spring Batch - Is it possible to write a custom restart in spring batch

I have been writing a spring batch wherein I have to perform some error-handling.
I know that spring batch has its own way of handling errors and restarts.
However, when the batch fails and restarts again, I want to pass my own values, conditions and parameters (for restart) which need to be followed before starting/executing the first step.
So, is it possible to write such custom restart in spring batch?
UPDATE1:(Providing a better explanation for above question.)
Let's say that the input to my reader in Step 1 is in the following format:
Table with following columns:
CompanyName1 -> VehicleId1
CN1 -> VID2
CN1 -> VID3
.
.
CN1 -> VID30
CN2 -> VID1
CN2 -> VID2
.
.
CNn -> VIDn
The reader reads this table row by row for a chunk size 1 (so in this case the row retrieved will be CN -> VID ) processes it and writes it to a File object.
This process goes on until all the CN1 type data is written into the File object. When the reader sends the row with company Name of type CN2 , the File object that was created earlier (for company name of type CN1) will be stored in a remote location. Then the process of File Object creation will continue for CN2 until we encounter CN3, in which case CN2 File Object will be sent for storage to a remote location
and the process will continue.
Now, once you understand this, here's a catch.
Let's say the data is currently being written by the writer for company Name 2 (CN2) and vehicle ID is VID20 (CN2 -> VID20)
in the File object. Then, due to some reason we had to stop the job/the job fails. In that case, the instance that will be saved will be CN2 -> VID20. So, next time when the job runs, it will start from CN2->VID20
As you might have guessed, all the 19 entries before CN2->VID20 which were written in the File Object were deleted permanently when the file Object got destroyed and these entries were never sent through the File to remote location.
So my question here is this:
Is there a way where I can write my custom restart for the batch where I could tell the job to start from CN2->VID1 instead of CN2->VID20?
If you could think of any other way to handle this scenario then such suggestions are also welcome.
Since you want to write the data of each company in a separate file, I would use the company name as a job parameter. With this approach:
Each job will read the data of a single company and write it to a file
If a job fails, you can restart it and it would resume where it left off (Spring Batch will truncate the file to last known written offset before writing new data). So there is no need for a custom restart "policy".
No need to set the chunk-size to 1, this is not efficient. You can use a reasonable chunk size with this approach
If the number of companies is small enough, you can run jobs manually. Otherwise, you can always get the distinct values with something like select distinct(company_name) from yourTable and write a script/loop to launch batch jobs with different parameters. Bottom line, make each job do one thing and do it well.

Access denied calling EnumJobs

I'm trying to get the domain username of jobs in a printer queue on Windows Server 2012 R2 Standard. Code snippet below is in Delphi. OpenPrinter and EnumJobs are part of the Windows Spooler API.
Update! Setting maxJobs to a higher multiple of 4 allows for more jobs in the queue to be enumerated. eg. Setting maxJobs=8 allows for two jobs, but not three. maxJobs=12 allows for three jobs.
Solved! It looks like I can just ignore the return value of EnumJobs, and simply see if the number of jobs it returns > 0 (the last argument when calling). This seems to work fine for all instances listed below, including printer via a share.
const
maxJobs = 4;
var
h : THandle;
jia : array [1..maxJobs] of JOB_INFO_1;
jiz, jic : DWord; // size of jia, count of jia
begin
if OpenPrinter('DocTest', h, nil) then
begin
if EnumJobs(h, 0, maxJobs, 1, #jia, SizeOf(jia), jiz, jic) then
[...]
EnumJobs returns true or false depending on different conditions listed below. If it returns false in any of the following situations, the error message I'm retrieving is "System Error. Code: 5. Access is denied".
Clearly a permissions problem. I have assigned Print, Manage this Printer, and Manage documents to Everyone in the printer security settings. All jobs have been submitted after those settings have been assigned. My program is running in a session logged in as the domain administrator.
EnumJobs returns TRUE if I print a job from the same session I'm running this program in, and there's only one job in the queue. (See Update above for change)
EnumJobs returns TRUE if I print from another session on the server (it has terminal services installed) as any user, and there's only one job in the queue. (See Update above for change)
EnumJobs returns FALSE if there is more than one job in the queue. It doesn't matter if the jobs are for the same user or not. (See Update above for change)
EnumJobs returns FALSE if I print a job from another server to the printer share. Both servers are in the same domain. It doesn't matter which user prints the job, including the domain administrator.
What's going on here, in particular getting an access denied when enumerating more than (maxJobs / 4) job(s) at a time?
Ignore the return value of EnumJobs and inspect the out argument pcReturned to see if it's greater than 0. This indicates the number of print jobs found.

How windows recovery work with failure count?

I am using the following command to configure the service failure recovery
sc failure "service" actions= ""/60000/restart/60000/run/120000 reset= 60 command = "\"c:\\windows\notepad2.exe
(used notepad2.exe just for testing)
From the Microsoft documentation here:-
Actions
This field contains an array of integer values that specify the
actions taken by the SCM if the service fails. Separate the values in
the array by [~]. The integer value in the Nth element of the array
specifies the action performed when the service fails for the Nth
time.
So, what I am getting from this is the count of failure will decide the action => For first failure Actions[0] will be executed and for the second Actions[1] will be executed and for all subsequent failures Actions[2] will be
I have following configuration for the service for testing this behavior:-
Then I tried killing the process under which service is running by using taskkill.
Here is the first log
Then I tried starting the service manually.
Then again I tried killing the service after ~ 2 mins ( => the reset count will set failure count to 0 as it is configured to 1 minute).
Here is the log for the error
In above figure, it is clear that why count is resetting to 0 because reset setting we have given60 sec and our service was running more than 2 mins.
But the action described for recovery is wrong as Restarting the service is the action for the second failure not for the first failure.
So why the count for failure is coming 1 but the action for recovery is the action corresponding to the second failure action?
I was just playing around with a similar issue, and after I set the "Reset fail count after:" to "1" day, it seems to be working. A possible explanation is that by setting the "Reset fail count" to 1 day, it will not reset the fail count back to 0 after the first fail (which is you stopping and restarting the service manually), and lets it cycle through the rest of the actions (depending on conditions/actions). Your mileage may vary.

Resources