|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 // system includes |
|
17 #include <schtask.h> |
|
18 |
|
19 // User includes |
|
20 #include "SCHEXEC.H" |
|
21 #include "SchLogger.h" |
|
22 #include "SCHLOG.h" |
|
23 #include "taskfile.h" |
|
24 |
|
25 //Delay ensuring this thread is be preempted allowing client cleanup |
|
26 //in case task file cannot be deleted |
|
27 const TInt KClientCleanupDelay = 10000; |
|
28 |
|
29 CTaskExecutor::CTaskExecutor(CSchLogManager& aSchLogManager) |
|
30 : CActive(EPriorityStandard), |
|
31 iSchLogManager(aSchLogManager) |
|
32 { |
|
33 CActiveScheduler::Add(this); |
|
34 } |
|
35 |
|
36 |
|
37 CTaskExecutor::~CTaskExecutor() |
|
38 { |
|
39 LOGSTRING("CTaskExecutor::~CTaskExecutor - start"); |
|
40 iProcess.Close(); |
|
41 |
|
42 // |
|
43 delete iClientFileName; |
|
44 delete iTaskFileName; |
|
45 delete iLogErrorMessage; |
|
46 LOGSTRING("CTaskExecutor::~CTaskExecutor - end"); |
|
47 } |
|
48 |
|
49 |
|
50 void CTaskExecutor::ConstructL(const TDesC& aTaskFileName, |
|
51 const TDesC& aClientFileName, |
|
52 const TDesC& aErrorMessage) |
|
53 { |
|
54 LOGSTRING("CTaskExecutor::ConstructL - start"); |
|
55 // Store filename |
|
56 iTaskFileName = aTaskFileName.AllocL(); |
|
57 iClientFileName = aClientFileName.AllocL(); |
|
58 |
|
59 // In case there is an error... |
|
60 iLogErrorMessage = aErrorMessage.AllocL(); |
|
61 |
|
62 LOGSTRING("CTaskExecutor::ConstructL - end"); |
|
63 } |
|
64 |
|
65 |
|
66 CTaskExecutor* CTaskExecutor::NewLC(const TDesC& aErrorMessage, |
|
67 const TDesC& aTaskFileName, |
|
68 const TDesC& aClientFileName, |
|
69 CSchLogManager& aSchLogManager) |
|
70 { |
|
71 LOGSTRING("CTaskExecutor::NewLC"); |
|
72 CTaskExecutor* self = new(ELeave) CTaskExecutor(aSchLogManager); |
|
73 CleanupStack::PushL(self); |
|
74 self->ConstructL(aTaskFileName, aClientFileName, aErrorMessage); |
|
75 return self; |
|
76 } |
|
77 |
|
78 void CTaskExecutor::RunL() |
|
79 { |
|
80 LOGSTRING3("CTaskExecutor::RunL - task finished running [client: %S, task: %S]", iClientFileName, iTaskFileName); |
|
81 // |
|
82 // RunL is called when the process/thread terminates |
|
83 // so that any error conditions can be handled. |
|
84 TInt exitReason = iProcess.ExitReason(); |
|
85 LOGSTRING2("CTaskExecutor::RunL - process exit reason was: %d", exitReason); |
|
86 |
|
87 // Close the process/thread |
|
88 iProcess.Close(); |
|
89 |
|
90 // Check for error code |
|
91 if (exitReason != KErrNone) |
|
92 { |
|
93 // Submit a log entry to record the error. |
|
94 LOGSTRING2("CTaskExecutor::RunL - recording unclean process exit (%d) in the log engine", exitReason); |
|
95 if(iLogErrorMessage) |
|
96 iSchLogManager.LogError(*iLogErrorMessage,exitReason); |
|
97 else |
|
98 iSchLogManager.LogError(exitReason); |
|
99 } |
|
100 |
|
101 // Clean up the file. Only delete it here once task process has finished. |
|
102 // If task process never started then file is deleted in CClientProxy code. |
|
103 User::LeaveIfError(iFsSession.Connect()); |
|
104 CleanupClosePushL(iFsSession); |
|
105 |
|
106 TInt fileDeleteErr = iFsSession.Delete(*iTaskFileName); |
|
107 |
|
108 // If unable to delete file wait and try again |
|
109 if (fileDeleteErr != KErrNone) |
|
110 { |
|
111 |
|
112 //Allow thread to be preempted to allow for cleanup of iProcess |
|
113 User::After(KClientCleanupDelay); |
|
114 |
|
115 fileDeleteErr = iFsSession.Delete(*iTaskFileName); |
|
116 |
|
117 // If still unable to delete file record the fact |
|
118 if (fileDeleteErr != KErrNone) |
|
119 { |
|
120 if(iLogErrorMessage) |
|
121 { |
|
122 iSchLogManager.LogError(*iLogErrorMessage, fileDeleteErr); |
|
123 } |
|
124 else |
|
125 { |
|
126 iSchLogManager.LogError(fileDeleteErr); |
|
127 } |
|
128 } |
|
129 } |
|
130 |
|
131 //Calls iFsSession::Close() so no need to call explicitly |
|
132 CleanupStack::PopAndDestroy(); |
|
133 |
|
134 // Delete outselves since we've finished |
|
135 LOGSTRING("CTaskExecutor::RunL - deleting ourself"); |
|
136 delete this; |
|
137 } |
|
138 |
|
139 void CTaskExecutor::DoCancel() |
|
140 { |
|
141 LOGSTRING("CTaskExecutor::DoCancel - start"); |
|
142 iProcess.LogonCancel(iStatus); |
|
143 // Delete file and ourselves since we can't do anything else. |
|
144 // We are in a bad state if we reach here but at least make the most of it. |
|
145 LOGSTRING("CTaskExecutor::DoCancel - deleting ourself"); |
|
146 |
|
147 //Connect to file session |
|
148 TInt err = iFsSession.Connect(); |
|
149 |
|
150 if(err == KErrNone) |
|
151 { |
|
152 err = iFsSession.Delete(*iTaskFileName); |
|
153 } |
|
154 |
|
155 // If unable to delete file record the fact |
|
156 if (err != KErrNone) |
|
157 { |
|
158 if(iLogErrorMessage) |
|
159 { |
|
160 iSchLogManager.LogError(*iLogErrorMessage, err); |
|
161 } |
|
162 else |
|
163 { |
|
164 iSchLogManager.LogError(err); |
|
165 } |
|
166 } |
|
167 |
|
168 //Close the file session |
|
169 iFsSession.Close(); |
|
170 |
|
171 delete this; |
|
172 LOGSTRING("CTaskExecutor::DoCancel - end"); |
|
173 } |
|
174 |
|
175 void CTaskExecutor::ExecuteL() |
|
176 { |
|
177 // If this leaves, CClientProxy should handle error.... |
|
178 // CTaskScheduler::ExecuteClients() traps the leave and then calls |
|
179 // CClientProxy::FailToExecute() to handle the error. |
|
180 #ifdef __SCHLOGGING__ |
|
181 { |
|
182 TTime time; time.HomeTime(); |
|
183 TDateTime due = time.DateTime(); |
|
184 LOGSTRING8("CTaskExecutor::ExecuteL - Executing tasks at: [%02d/%02d/%d] @ %02d:%02d:%02d.%05d", due.Day(), (TInt) due.Month() + 1, due.Year(), due.Hour(), due.Minute(), due.Second(), due.MicroSecond()); |
|
185 } |
|
186 #endif |
|
187 |
|
188 // Create a new process and pass the name of the task file as the command line argument |
|
189 // (data for the target exe). |
|
190 LOGSTRING("CTaskExecutor::ExecuteL - creating process"); |
|
191 TInt err = iProcess.Create(*iClientFileName, KNullDesC); |
|
192 |
|
193 // Will check the error, report the problem and leave (if err<KErrNone) |
|
194 // otherwise does nothing. |
|
195 LOGSTRING("CTaskExecutor::ExecuteL - checking process creation error code"); |
|
196 CheckErrorAndLeaveL(err); |
|
197 |
|
198 // connect to new file session to avoid possible security |
|
199 // consequences if lauched process tries to use passed file in |
|
200 // subversive way. |
|
201 User::LeaveIfError(iFsSession.Connect()); |
|
202 CleanupClosePushL(iFsSession); |
|
203 User::LeaveIfError(iFsSession.ShareProtected()); |
|
204 |
|
205 User::LeaveIfError(iTaskFile.Open(iFsSession, *iTaskFileName, EFileRead)); |
|
206 CleanupClosePushL(iTaskFile); |
|
207 |
|
208 // transfer file handle to launched process |
|
209 err = iTaskFile.TransferToProcess(iProcess, KTaskFsHandleIndex, KTaskFileHandleIndex); |
|
210 |
|
211 //Close task file and session handles |
|
212 //Calls iFsSession::Close() and iTaskFile::Close() so no need to call explicitly |
|
213 CleanupStack::PopAndDestroy(2); |
|
214 |
|
215 CheckErrorAndLeaveL(err); |
|
216 |
|
217 // Asynchronous logon: completes when process terminates with process exit code |
|
218 iProcess.Logon(iStatus); |
|
219 iProcess.Resume(); |
|
220 |
|
221 SetActive(); |
|
222 LOGSTRING("CTaskExecutor::ExecuteL - end"); |
|
223 |
|
224 } |
|
225 |
|
226 void CTaskExecutor::CheckErrorAndLeaveL(TInt aError) |
|
227 { |
|
228 if (aError < KErrNone) |
|
229 { |
|
230 if(iLogErrorMessage) |
|
231 iSchLogManager.LogError(*iLogErrorMessage,aError); |
|
232 else |
|
233 iSchLogManager.LogError(aError); |
|
234 User::Leave(aError); |
|
235 } |
|
236 } |
|
237 |