1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
|
8 krisbash 1.3 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
|
13 mike 1.1 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15 krisbash 1.3 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
|
18 mike 1.1 **
|
19 krisbash 1.3 ** See the Apache 2 License for the specific language governing permissions
|
20 mike 1.1 ** and limitations under the License.
21 **
22 **==============================================================================
23 */
24
|
25 krisbash 1.3 #include <pal/strings.h>
|
26 mike 1.1 #include <base/messages.h>
27 #include <base/log.h>
|
28 krisbash 1.3 #include <pal/strings.h>
|
29 mike 1.1 #include <base/paths.h>
|
30 krisbash 1.3 #include <pal/format.h>
31 #include <base/Strand.h>
|
32 mike 1.1 #include <protocol/protocol.h>
33 #include "agentmgr.h"
|
34 krisbash 1.3 #include <omi_error/errorutil.h>
|
35 mike 1.1
36 #if defined(CONFIG_POSIX)
37 # include <unistd.h>
38 # include <errno.h>
39 # include <sys/socket.h>
40 # include <netinet/tcp.h>
41 # include <netinet/in.h>
42 # include <sys/time.h>
43 # include <sys/types.h>
44 # include <netdb.h>
45 # include <fcntl.h>
46 # include <arpa/inet.h>
47 # include <signal.h>
48 # include <sys/wait.h>
49 #endif
50
51 /*
52 **==============================================================================
53 **
54 ** Data structures
55 **
56 mike 1.1 **==============================================================================
57 */
58
59 #if defined(CONFIG_POSIX)
60
61 /*
62 RequestItem - stores information about request sent to the agent/provider;
|
63 krisbash 1.3 this item stores original request's operationId (has to be substituted) and request pointer
64 In case of agent disconnection, agent-mgr uses this list to send error responses to
|
65 mike 1.1 outstanding requests.
66 */
|
67 krisbash 1.3
68 typedef enum _RequestItemFinishState
|
69 mike 1.1 {
|
70 krisbash 1.3 RequestItemFinishState_None = 0,
71 RequestItemFinishState_PendingFinishOnError,
72 RequestItemFinishState_ProcessedFinishOnError
73 } RequestItemFinishState;
74
75
76 typedef struct _RequestItem
77 {
78 // managing original interaction coming from dispatcher
79 StrandEntry strand;
|
80 mike 1.1
|
81 krisbash 1.3 MI_Boolean isIdleRequest;
82 MI_Boolean pendingCancel;
83 RequestItemFinishState finishOnErrorState;
84
85 Message* request; // Request received from the left
86 MI_Uint64 originalOperationId;
87 MI_Uint64 key; // OperationId of the outogoing request; for now RequestItem address (as it was before)
88 }
89 RequestItem;
|
90 mike 1.1
91 /*
92 AgentElem - stores information about single running agent
|
93 krisbash 1.3 (this will be become multiplexer eventually)
|
94 mike 1.1 */
95 struct _AgentElem
96 {
|
97 krisbash 1.3 StrandMany strand;
98
|
99 mike 1.1 /* Linked-list support */
|
100 krisbash 1.3 ListElem* next;
101 ListElem* prev;
|
102 mike 1.1
103 /* hosting context */
|
104 krisbash 1.3 uid_t uid;
105 gid_t gid;
|
106 mike 1.1
107 /* connection to the agent */
|
108 krisbash 1.3 ProtocolSocketAndBase* protocol;
|
109 mike 1.1
110 /* link to manager */
|
111 krisbash 1.3 AgentMgr* agentMgr;
|
112 mike 1.1
113 /* agent process pid */
|
114 krisbash 1.3 pid_t agentPID;
|
115 mike 1.1 };
116
117 /*
118 **==============================================================================
|
119 krisbash 1.3 */
120
121 #define AGENTELEM_STRANDAUX_CLOSEAGENTITEM 0
122 #define AGENTELEM_STRANDAUX_ENTRYACK 1
123
124 STRAND_DEBUGNAME2( AgentElem, CloseAgentItem, EntryAck );
125
126 #define IDLEREQUESTITEM_STRANDAUX_READYTOFINISH 0
127
128 STRAND_DEBUGNAME1( IdleRequestItem, ReadyToFinish );
129
130 #define REQUESTITEM_STRANDAUX_PREPARETOFINISHONERROR 0
131
132 STRAND_DEBUGNAME1( RequestItem, PrepareToFinishOnError );
133
134
135 /*
136 **==============================================================================
137 */
138
139 void _AgentElem_InitiateClose( _In_ AgentElem* self )
140 krisbash 1.3 {
141 // remove agent from Mgr's list
142 // Do this first so no new request entries are added after this
143 ReadWriteLock_AcquireWrite(&self->agentMgr->lock);
144 List_Remove(
145 &self->agentMgr->headAgents,
146 &self->agentMgr->tailAgents,
147 (ListElem*)&(self->next));
148 ReadWriteLock_ReleaseWrite(&self->agentMgr->lock);
149
150 StrandMany_ScheduleAux( &self->strand, AGENTELEM_STRANDAUX_CLOSEAGENTITEM );
151 }
152
153 void _AgentElem_Post( _In_ Strand* self_, _In_ Message* msg)
154 {
155 AgentElem* self = (AgentElem*)StrandMany_FromStrand(self_);
156 DEBUG_ASSERT( NULL != self_ );
157 trace_AgentElemPostingMessage(&self->strand.strand.info.interaction, self->strand.strand.info.interaction.other);
158
159 /* ATTN: verify unload message */
160
161 krisbash 1.3 if (BinProtocolNotificationTag == msg->tag)
162 {
163 BinProtocolNotification* notification = (BinProtocolNotification*)msg;
164 if (BinNotificationAgentIdle == notification->type)
165 {
166 // Check if this agent has outstanding requests -
167 // if agent is really idle (only idle notification request)
168 // then initiate the close
169 if( 1 == self->strand.numEntries )
170 {
171 _AgentElem_InitiateClose( self );
172 }
173 }
174 /* ignore service messages */
175 Strand_Ack( &self->strand.strand );
176 return;
177 }
178
179 if( !StrandMany_PostFindEntry( &self->strand, msg ) )
180 {
181 trace_StrandMany_CannotFindItem( Uint64ToPtr(msg->operationId), (int)self->uid );
182 krisbash 1.3 _AgentElem_InitiateClose( self );
183 }
184
185 // For now ack immediately
186 //TODO eventually multiplexer should take care of flow control here
187 // For now, we are short circuiting ACK from RequstItem
188 }
189
190 void _AgentElem_PostControl( _In_ Strand* self_, _In_ Message* msg)
191 {
192 DEBUG_ASSERT( MI_FALSE ); // not used yet
193 }
194
195 void _AgentElem_Ack( _In_ Strand* self_)
196 {
197 trace_AgentElemAck( &self_->info.interaction, self_->info.interaction.other );
198 }
199
200 void _AgentElem_Cancel( _In_ Strand* self_)
201 {
202 DEBUG_ASSERT( MI_FALSE ); // not used yet
203 krisbash 1.3 }
204
205 void _AgentElem_Close( _In_ Strand* self_)
206 {
207 AgentElem* self = (AgentElem*)StrandMany_FromStrand(self_);
208
209 trace_AgentClosedConnection((int)self->uid);
210 // lost connection to the agent ( within 'CloseAgentItem' call):
211 // - send error repsonses to all outstanding requests
212 // - remove agent form the list
213
214 _AgentElem_InitiateClose( self );
215 }
216
217 void _AgentElem_Finish( _In_ Strand* self_)
218 {
219 AgentElem* self = (AgentElem*)StrandMany_FromStrand(self_);
220 DEBUG_ASSERT( NULL != self_ );
221
222 // It is ok now for the protocol object to go away
223 ProtocolSocketAndBase_ReadyToFinish(self->protocol);
224 krisbash 1.3
225 StrandMany_Delete(&self->strand);
226 }
227
228 // AGENTELEM_STRANDAUX_ENTRYACK
229 void _AgentElem_EntryAck( _In_ Strand* self_)
230 {
231 //Temporary until we have flow control with multiplexing buffers
232 Strand_Ack( self_ );
233
234 }
235
236 // AGENTELEM_STRANDAUX_CLOSEAGENTITEM
237 static void _AgentElem_CloseAgentItem(Strand* self_);
238
239 /*
240 Object that implements a single connection going thru binary protocol
241 to one agent. It uses that one-to-many interface to channel thru multiple
242 operations on the same connection.
243
244 Behavior:
245 krisbash 1.3 - Post checks if the message is a idle notification, and if it is and there is
246 only one remaining operation (the idle notification one itself) then initiates
247 a close. Otherwise it just post the message to the pertinent operation that is
248 find using the buildin hash map searching by the operationId field
249 in the message.
250 - Ack does nothing currently as there is not an explicit in-the-wire flow control
251 protocol implemented yet.
252 - PostControl and Cancel are not currently implemented
253 - Close initiates the closing of all entries and sending the corresponding
254 error messages to each one (see _AgentElem_CloseAgentItem below)
255 - Shutdown:
256 The objects are deleted thru the normal Strand logic. That is,
257 once the interaction is closed on both sides and there are no
258 entries the object is auto-deleted.
259
260 Unique features and special Behavour:
261 - _AgentElem_CloseAgentItem is called at any time is there is an unrecoverable
262 error or the connection has been lost and it will iterate thru the existing
263 operations/requests sending an appropiate error message to each one.
264 - _AgentElem_EntryAck is schedule by each entry (RequestItem) when it
265 receives and Ack so that Ack can be simply passed thru to the connection
266 krisbash 1.3 (since we dont have yet a more sophisticated on-the-wire flow control
267 mechanism).
268 */
269 static StrandFT _AgentElem_FT = {
270 _AgentElem_Post,
271 _AgentElem_PostControl,
272 _AgentElem_Ack,
273 _AgentElem_Cancel,
274 _AgentElem_Close,
275 _AgentElem_Finish,
276 NULL,
277 _AgentElem_CloseAgentItem,
278 _AgentElem_EntryAck,
279 NULL,
280 NULL,
281 NULL };
282
283 /*
284 **==============================================================================
285 */
286
287 krisbash 1.3 static MI_Result _PrepareMessageForAgent(
288 MI_Uint64 operationId,
289 _In_ Message* msg,
290 _Out_ Message** msgOut)
291 {
292 MI_Result result;
293
294 /* clone message (may be incoming message in some cases) */
295 result = MessagePackCloneForBinarySending(msg, msgOut);
296 if( MI_RESULT_OK == result )
297 {
298 /* substitute message-id on time server->agent call;
299 operationId has to be restored once first response is received */
300 (*msgOut)->operationId = operationId;
301 (*msgOut)->flags = msg->flags;
302 }
303 else
304 {
305 trace_SendRequestToAgent_MessageCloneFailed(result);
306 }
307
308 krisbash 1.3 return result;
309 }
310
311 static void _SendErrorResponseAndClose(
312 RequestItem* requestItem,
313 MI_Result r)
314 {
315 PostResultMsg* resp;
316 trace_AgentMgr_SendErrorResponse( requestItem );
317 resp = PostResultMsg_NewAndSerialize( requestItem->request, NULL, NULL, MI_RESULT_TYPE_MI, r);
318
319 //TODO - do a force close
320 if (!resp)
321 return;
322
323 requestItem->request->operationId = requestItem->originalOperationId;
324
325 requestItem->finishOnErrorState = RequestItemFinishState_ProcessedFinishOnError;
326 Strand_Post(&requestItem->strand.strand, &resp->base);
327
328 PostResultMsg_Release(resp);
329 krisbash 1.3
330 Strand_Close(&requestItem->strand.strand);
331 }
332
333 // not used much yet (no secondary "semantic" messages at the time)
334 // currently used for unsubscribe message
335 void _RequestItem_Post( _In_ Strand* self_, _In_ Message* msg)
336 {
337 RequestItem* self = (RequestItem*)StrandEntry_FromStrand(self_);
338 MI_Result result;
339 Message* msgOut = NULL;
340
341 DEBUG_ASSERT( NULL != self_ );
342 trace_RequestItemPostingMessage( self_, &self->strand.strand.info.interaction, self->strand.strand.info.interaction.other );
343
344 result = _PrepareMessageForAgent( self->key, msg, &msgOut );
345 if( MI_RESULT_OK == result )
346 {
347 StrandEntry_PostParentPassthru(&self->strand, msgOut);
348 Message_Release(msgOut);
349 }
350 krisbash 1.3 else
351 {
352 trace_RequestItem_PostFailed(result);
353 }
354 }
355
356 void _RequestItem_PostControl( _In_ Strand* self_, _In_ Message* msg)
357 {
358 DEBUG_ASSERT( MI_FALSE ); // not used yet
359 }
360
361 void _RequestItem_Ack( _In_ Strand* self_)
362 {
363 RequestItem* self = (RequestItem*)StrandEntry_FromStrand(self_);
364 DEBUG_ASSERT( NULL != self_ );
365 trace_RequestItemAck( &self_->info.interaction, self_->info.interaction.other );
366
367 if (self->finishOnErrorState != RequestItemFinishState_ProcessedFinishOnError)
368 {
369 StrandEntry_ScheduleAuxParent( &self->strand, AGENTELEM_STRANDAUX_ENTRYACK );
370 }
371 krisbash 1.3
372 if (self->finishOnErrorState == RequestItemFinishState_PendingFinishOnError)
373 {
374 //this is going to set finishOnErrorState to processed state
375 _SendErrorResponseAndClose(self, MI_RESULT_FAILED);
376 }
377
378
379 //TODO eventually multiplexer "WITH FC Buffers" should take care of flow control here
380 }
381
382 void _RequestItem_SendCancel( _In_ RequestItem* self )
383 {
384 CancelMsg* msg = CancelMsg_New(self->originalOperationId); // this will get transformed on _SendMessageToAgent
385 MI_Result result;
386 Message* msgOut = NULL;
387
388 DEBUG_ASSERT( NULL != self );
389
390 trace_RequestItemCancel( &self->strand.strand );
391
392 krisbash 1.3
393 if( NULL != msg )
394 {
395 result = _PrepareMessageForAgent( self->key, &msg->base, &msgOut );
396 if( MI_RESULT_OK == result )
397 {
398 StrandEntry_PostParent(&self->strand, msgOut);
399 Message_Release(msgOut);
400 }
401 else
402 {
403 trace_RequestItem_Cancel_PrepMessageFailed(result);
404 }
405 CancelMsg_Release(msg);
406 }
407 else
408 {
409 trace_RequestItem_Cancel_CancelMsg_NewFailed();
410 }
411 }
412
413 krisbash 1.3 void _RequestItem_Cancel( _In_ Strand* self_ )
414 {
415 RequestItem* self = (RequestItem*)StrandEntry_FromStrand(self_);
416
417 if( self->strand.strand.info.otherAckPending )
418 {
419 DEBUG_ASSERT( self->strand.ackPassthru );
420 // Do nothing now, when the Ack from parent arrives we will send the message
421 self->pendingCancel = MI_TRUE;
422 }
423 else
424 {
425 _RequestItem_SendCancel( self );
426 }
427 }
428
429 void _RequestItem_Finish( _In_ Strand* self_)
430 {
431 RequestItem* self = (RequestItem*)StrandEntry_FromStrand(self_);
432
433 // release request before we delete the entry
434 krisbash 1.3 if( NULL != self->request )
435 {
436 Message_Release(self->request);
437 self->request = NULL;
438 }
439
440 StrandEntry_Delete( &self->strand );
441 }
442
443 // REQUESTITEM_STRANDAUX_PREPARETOFINISHONERROR
444 void _RequestItem_PrepareToFinishOnError( _In_ Strand* self_)
445 {
446 RequestItem* self = (RequestItem*)StrandEntry_FromStrand(self_);
447
448 //if we already closed other
449 if (self_->info.thisClosedOther)
450 return;
451
452 //if there isn't an ack pending on a previous post, send the final response
453 if (!self_->info.thisAckPending)
454 {
455 krisbash 1.3 _SendErrorResponseAndClose(self, MI_RESULT_FAILED);
456 return;
457 }
458
459 //else mark for finish when the next ack arrives
460 self->finishOnErrorState = RequestItemFinishState_PendingFinishOnError;
461 }
462
463 /*
464 Object that implements a single operation/request going to an agent thru
465 a binary protocol connection. Uses that one-to-many interface to multiplex multiple
466 operations in a single connection (AgentElem).
467
468 Behavior:
469 - Post calls _PrepareMessageForAgent to adapt the message to be send on the
470 wire the uses StrandEntry_PostParentPassthru to post to the parent
471 using the default many-to-one post implementation that enques the message
472 on the AgentElem
473 - Ack checks on the state of finishOnErrorState. On the normal case the ack is
474 just passed thru to the parent by using AGENTELEM_STRANDAUX_ENTRYACK
475 but if the state is RequestItemFinishState_PendingFinishOnError then an
476 krisbash 1.3 error is send instead and if the state is RequestItemFinishState_ProcessedFinishOnError
477 it means nothing else is needed.
478 - PostControl is not currently implemented
479 - Cancel check if there is an Ack pending on the other side of the interaction (dispatcher)
480 what means that in that case the cancel cannot be sent immediately and just
481 set pendingCancel to true (see _RequestItem_ParentAck below). Otherwise sends
482 the cancel immediately.
483 - Close uses the default implementation
484 - Shutdown:
485 The objects are deleted thru the normal Strand logic. That is,
486 once the interaction is closed on both sides the object is auto-deleted.
487 Note that the interaction is closed once the final message is received as
488 noted in _RequestItem_ParentPost below
489
490 Unique features and special Behavour:
491 - _RequestItem_PrepareToFinishOnError is scheduled when the parent
492 _AgentElem_CloseAgentItem execute, that is, when for some reason
493 the connection to the agent needs to be closed. In that case it checks
494 if the Interaction has been already closed (so it doesnt need to do anything),
495 or if there is an Ack pending on the other side of the interaction (dispatcher)
496 what means that in that case the cancel cannot be sent immediately and just
497 krisbash 1.3 sets finishOnErrorState RequestItemFinishState_PendingFinishOnError.
498 Otherwise it will directly send the error response and close the interaction
499 (finishOnErrorState will be set to RequestItemFinishState_ProcessedFinishOnError
500 in that case).
501 - _RequestItem_AddedToParent is used to deliver the initial request ONCE
502 the Item has been added to the parent AgentElem connection
503 - _RequestItem_ParentPost just post the message from the parent back to
504 the left interaction (typically dispatcher) unless the connection has already being
505 closed for some reason. It restores the original operationId that is replaced in
506 the connection to the agent and it also checks if the message is a final message,
507 in which case closes the interaction.
508 - _RequestItem_ParentAck checks if the corresponding Post was PassThru
509 and in that case sends the Ack passThru. It also checks if there was a pending
510 cancel to be send (see Cancel above) and send its now that is possible.
511 */
512 static StrandFT _RequestItem_FT = {
513 _RequestItem_Post,
514 _RequestItem_PostControl,
515 _RequestItem_Ack,
516 _RequestItem_Cancel,
517 NULL,
518 krisbash 1.3 _RequestItem_Finish,
519 NULL,
520 _RequestItem_PrepareToFinishOnError,
521 NULL,
522 NULL,
523 NULL,
524 NULL };
525
526
527 void _IdleRequestItem_Post( _In_ Strand* self_, _In_ Message* msg)
528 {
529 DEBUG_ASSERT( MI_FALSE ); // not used
530 }
531
532 void _IdleRequestItem_PostControl( _In_ Strand* self_, _In_ Message* msg)
533 {
534 DEBUG_ASSERT( MI_FALSE ); // not used
535 }
536
537 void _IdleRequestItem_Ack( _In_ Strand* self_ )
538 {
539 krisbash 1.3 DEBUG_ASSERT( MI_FALSE ); // not used
540 }
541
542 void _IdleRequestItem_Finish( _In_ Strand* self_)
543 {
544 RequestItem* self = (RequestItem*)StrandEntry_FromStrand(self_);
545
546 DEBUG_ASSERT( NULL == self->request );
547
548 StrandEntry_Delete( &self->strand );
549 }
550
551 // IDLEREQUESTITEM_STRANDAUX_READYTOFINISH
552 void _IdleRequestItem_ReadyToFinish( _In_ Strand* self_)
553 {
554 RequestItem* self = (RequestItem*)StrandEntry_FromStrand(self_);
555
556 Strand_ResetDelayFinish(&self->strand.strand);
557 }
558
559 /*
560 krisbash 1.3 Object that implements the especific request needed to receive the Idle notification
561 from the agent. It is attached as one Entries on the one-to-many interface with the
562 agent connection (AgentElem).
563
564 Behavior:
565 - Post, PostControl and Ack are never used
566 - Shutdown:
567 The object is not deleted thru the normal Strand logic but only
568 when the connection is finished. For that SetDelayFinish is set,
569 and only reset when _IdleRequestItem_ReadyToFinish is called,
570 what would happen when the parent agentElem is closed.
571 Aalso note the the idle notification is processed directly by the
572 AgentElem as never reaches the IdleRequestItem.
573 IdleRequestItem is only used to initiate the corresponding object,
574 IdleNotification, in the agent )
575 */
576 static StrandFT _IdleRequestItem_FT = {
577 _IdleRequestItem_Post,
578 _IdleRequestItem_PostControl,
579 _IdleRequestItem_Ack,
580 NULL,
581 krisbash 1.3 NULL,
582 _IdleRequestItem_Finish,
583 NULL,
584 _IdleRequestItem_ReadyToFinish,
585 NULL,
586 NULL,
587 NULL,
588 NULL };
589
590 /*
591 **==============================================================================
592 */
593
594 void _AgentElem_NewEntry( _In_ StrandMany* self, _In_ StrandEntry* newEntry, _In_opt_ Message* msg, _Inout_ MI_Boolean* failed )
595 {
596 DEBUG_ASSERT( NULL != failed );
597 DEBUG_ASSERT( !(*failed) ); //TODO process this properly
598
599 // Nothing to do here. The entry will post its initial message once it receives AddedToParent
600 }
601
602 krisbash 1.3 void _RequestItem_AddedToParent( _In_ StrandEntry* self, _In_ Message* msg )
603 {
604 RequestItem* requestItem = (RequestItem*)self;
605
606 DEBUG_ASSERT( NULL != msg );
607
608 if( requestItem->isIdleRequest )
609 {
610 // There is no Interaction to deliver an Ack in this case
611 StrandEntry_PostParent( &requestItem->strand, msg );
612 }
613 else
614 {
615 StrandEntry_PostParentPassthru( &requestItem->strand, msg );
616 }
617 }
618
619 // Message back from protocol
620 void _RequestItem_ParentPost( _In_ StrandEntry* self, _In_ Message* msg)
621 {
622 RequestItem* requestItem = (RequestItem*)self;
623 krisbash 1.3 //should never receive a parent post when the parent previously told us to wrap up things on error
624 DEBUG_ASSERT(requestItem->finishOnErrorState == RequestItemFinishState_None);
625
626 if( self->strand.info.thisClosedOther )
627 {
628 trace_RequestItem_ParentPost_AfterClose( requestItem, msg );
629 }
630 else
631 {
632 trace_RequestItemParentPost( requestItem, msg );
633
634 /* restore operationId */
635 requestItem->request->operationId = requestItem->originalOperationId;
636 msg->operationId = requestItem->originalOperationId;
637
638 Strand_Post( &requestItem->strand.strand, msg );
639
640 /* remove item if result received */
641 if( Message_IsFinalResponse(msg) )
642 {
643 // Now we can close interaction (nothing else is going to be posted)
644 krisbash 1.3 Strand_Close( &requestItem->strand.strand );
645 }
646 }
647 }
648
649 void _RequestItem_ParentAck(_In_ StrandEntry* self)
650 {
651 RequestItem* requestItem = (RequestItem*)self;
652
653 if( !requestItem->isIdleRequest )
654 {
655 if( requestItem->strand.ackPassthru )
656 {
657
658 if( requestItem->pendingCancel )
659 {
660 requestItem->pendingCancel = MI_FALSE;
661 _RequestItem_SendCancel( requestItem );
662 }
663
664 Strand_Ack( &self->strand );
665 krisbash 1.3 }
666 else
667 {
668 //only case we do a Parent Post without a need to ackPassthru is when
669 //posting CancelMsg (See _RequestItem_SendCancel). The strand should have been in canceled state by then
670 DEBUG_ASSERT(self->strand.canceled);
671 }
672 }
673 else
674 {
675 DEBUG_ASSERT( !requestItem->strand.ackPassthru );
676 }
677 }
678
679 static StrandManyInternalFT _AgentElem_InternalFT = {
680 _AgentElem_NewEntry,
681 NULL,
682 NULL,
683 NULL,
684 NULL,
685 _RequestItem_AddedToParent,
686 krisbash 1.3 _RequestItem_ParentPost,
687 NULL,
688 _RequestItem_ParentAck,
689 NULL };
690 /*
691 **==============================================================================
|
692 mike 1.1 **
693 ** Local functions
694 **
695 **==============================================================================
696 */
|
697 krisbash 1.3 static MI_Uint64 _NextOperationId()
698 {
699 static ptrdiff_t _operationId = 0;
700 return (MI_Uint64) Atomic_Inc(&_operationId);
701 }
702
703
704 // Called with AgentMgr lock acquired
|
705 mike 1.1 static AgentElem* _FindAgent(
706 AgentMgr* self,
707 uid_t uid,
708 gid_t gid)
709 {
710 AgentElem* agent;
|
711 krisbash 1.3 ListElem* elem;
|
712 mike 1.1
|
713 krisbash 1.3 elem = self->headAgents;
|
714 mike 1.1
|
715 krisbash 1.3 while (elem)
|
716 mike 1.1 {
|
717 krisbash 1.3 agent = FromOffset(AgentElem,next,elem);
718
|
719 mike 1.1 if (uid == agent->uid && gid == agent->gid)
|
720 krisbash 1.3 {
|
721 mike 1.1 return agent;
|
722 krisbash 1.3 }
|
723 mike 1.1
|
724 krisbash 1.3 elem = elem->next;
|
725 mike 1.1 }
|
726 krisbash 1.3
|
727 mike 1.1 return 0;
728 }
729
730 static pid_t _SpawnAgentProcess(
731 Sock s,
732 int logfd,
733 uid_t uid,
734 gid_t gid,
735 const char* provDir,
736 MI_Uint32 idletimeout)
737 {
738 pid_t child;
739 int fdLimit;
740 int fd;
741 char param_sock[32];
742 char param_logfd[32];
743 char param_idletimeout[32];
|
744 krisbash 1.3 const char* agentProgram = OMI_GetPath(ID_AGENTPROGRAM);
|
745 mike 1.1
746 child = fork();
747
748 if (child < 0)
749 return -1; /* Failed */
750
751 if (child > 0)
752 return child; /* Started */
753
754 /* We are in child process here */
755
756 /* switch user */
757 if (0 != SetUser(uid,gid))
758 {
759 _exit(1);
760 }
761
762 /* Close all open file descriptors except provided socket
763 (Some systems have UNLIMITED of 2^64; limit to something reasonable) */
764
765 fdLimit = getdtablesize();
766 mike 1.1 if (fdLimit > 2500 || fdLimit < 0)
767 {
768 fdLimit = 2500;
769 }
770
771 /* ATTN: close first 3 also! Left for debugging only */
772 for (fd = 3; fd < fdLimit; ++fd)
773 {
774 if (fd != s && fd != logfd)
775 close(fd);
776 }
777
778 /* prepare parameter:
779 socket fd to attach */
780 Snprintf(param_sock, sizeof(param_sock), "%d", (int)s);
781 Snprintf(param_logfd, sizeof(param_logfd), "%d", (int)logfd);
782 Snprintf(param_idletimeout, sizeof(param_idletimeout), "%d", (int)idletimeout);
783
|
784 krisbash 1.3 execl(agentProgram,
785 agentProgram,
|
786 mike 1.1 param_sock,
787 param_logfd,
788 "--destdir",
|
789 krisbash 1.3 OMI_GetPath(ID_DESTDIR),
|
790 mike 1.1 "--providerdir",
791 provDir,
792 "--idletimeout",
793 param_idletimeout,
794 "--loglevel",
795 Log_GetLevelString(Log_GetLevel()),
796 NULL);
797
|
798 krisbash 1.3 trace_AgentLaunch_Failed(scs(agentProgram), errno);
799 _exit(1);
|
800 mike 1.1 return -1; /* never get here */
801 }
802
|
803 krisbash 1.3 static void _AgentElem_CloseAgentItem( Strand* self_ )
|
804 mike 1.1 {
|
805 krisbash 1.3 AgentElem* agent = (AgentElem*)StrandMany_FromStrand(self_);
806 RequestItem* requestItem;
|
807 mike 1.1
|
808 krisbash 1.3 StrandMany_BeginIteration( &agent->strand );
|
809 mike 1.1
810 /* send error repsonses to all outstanding requests */
|
811 krisbash 1.3 while( NULL != (requestItem = (RequestItem*)StrandMany_Iterate( &agent->strand )) )
|
812 mike 1.1 {
|
813 krisbash 1.3 if( requestItem->isIdleRequest )
814 {
815 StrandEntry_ScheduleAux(&requestItem->strand, IDLEREQUESTITEM_STRANDAUX_READYTOFINISH );
816 }
817 else
818 {
819 StrandEntry_ScheduleAux(&requestItem->strand, REQUESTITEM_STRANDAUX_PREPARETOFINISHONERROR );
820 }
821 // No need to call StrandMany_DeleteEntry(&requestItem->strand) to delete requestItem (it would do so itself )
|
822 mike 1.1 }
823
824 if (agent->protocol)
|
825 krisbash 1.3 {
826 // We can now close the interaction with protocol if not done already
827 if( !agent->strand.strand.info.thisClosedOther )
828 Strand_Close( &agent->strand.strand );
829 }
830 else
831 {
832 agent->strand.strand.info.thisClosedOther = agent->strand.strand.info.otherClosedThis = MI_TRUE;
833 }
|
834 mike 1.1
835 /* SIGCHILD HANDLER will take care of pid waiting */
836 /*if (agent->agentPID > 0)
837 {
838 int loc = 0;
839 pid_t p = waitpid(agent->agentPID, &loc, WNOHANG);
840
841 LOGI_CHAR(("waitpid returned %d, loc %d",(int)p, loc));
842
843 if (p != agent->agentPID)
844 {
845 kill(agent->agentPID, SIGKILL);
846 p = waitpid(agent->agentPID, &loc, WNOHANG);
847
848 LOGW_CHAR(("sent KILL; waitpid returned %d, loc %d",(int)p, loc));
849 }
850 }*/
851
|
852 krisbash 1.3 // the AgentElem should delete itself on Finish
|
853 mike 1.1 }
854
|
855 krisbash 1.3 size_t _AgentElem_HashMapHashProc(const HashBucket* bucket)
|
856 mike 1.1 {
|
857 krisbash 1.3 const RequestItem* self = (const RequestItem*)StrandEntry_FromBucketConst(bucket);
858 return (size_t)self->key;
859 }
|
860 mike 1.1
|
861 krisbash 1.3 int _AgentElem_HashMapEqualProc(_In_ const HashBucket* bucket1, _In_ const HashBucket* bucket2)
862 {
863 const RequestItem* entry1 = (const RequestItem*)StrandEntry_FromBucketConst(bucket1);
864 const RequestItem* entry2 = (const RequestItem*)StrandEntry_FromBucketConst(bucket2);
865 return entry1->key == entry2->key;
|
866 mike 1.1 }
867
|
868 krisbash 1.3 StrandEntry* _AgentElem_FindRequest(_In_ const StrandMany* parent, _In_ const Message* msg)
|
869 mike 1.1 {
|
870 krisbash 1.3 AgentElem* agent = (AgentElem*)parent;
871 RequestItem forSearch;
872 HashBucket* bucket;
|
873 mike 1.1
|
874 krisbash 1.3 forSearch.key = msg->operationId;
|
875 mike 1.1
|
876 krisbash 1.3 bucket = HashMap_Find(&agent->strand.many,&forSearch.strand.bucket);
|
877 mike 1.1
|
878 krisbash 1.3 if( NULL == bucket )
|
879 mike 1.1 {
|
880 krisbash 1.3 trace_AgentElem_FindRequest_CannotFindKey( agent, &agent->strand.strand, forSearch.key );
881 return NULL;
|
882 mike 1.1 }
|
883 krisbash 1.3 else
|
884 mike 1.1 {
|
885 krisbash 1.3 RequestItem* self = (RequestItem*)StrandEntry_FromBucket(bucket);
886 trace_AgentElemFoundKey( agent, &agent->strand.strand, forSearch.key, self, &self->strand.strand );
887 return (StrandEntry*)self;
|
888 mike 1.1 }
889 }
890
|
891 krisbash 1.3 // Called with AgentMgr lock acquired
|
892 mike 1.1 static AgentElem* _CreateAgent(
|
893 krisbash 1.3 _In_ AgentMgr* self,
|
894 mike 1.1 uid_t uid,
|
895 krisbash 1.3 gid_t gid )
|
896 mike 1.1 {
897 AgentElem* agent = 0;
898 Sock s[2];
899 int logfd = -1;
|
900 krisbash 1.3 InteractionOpenParams interactionParams;
|
901 mike 1.1
902 /* create communication pipe */
903 if(0 != socketpair(AF_UNIX, SOCK_STREAM, 0, s))
904 {
|
905 krisbash 1.3 trace_SocketPair_Failed();
|
906 mike 1.1 return 0;
907 }
908
909 if (MI_RESULT_OK != Sock_SetBlocking(s[0], MI_FALSE) ||
910 MI_RESULT_OK != Sock_SetBlocking(s[1], MI_FALSE))
911 {
|
912 krisbash 1.3 trace_SetNonBlocking_Failed();
|
913 mike 1.1 goto failed;
914 }
915
916 /* create/open log file for agent */
917 {
|
918 krisbash 1.3 char path[PAL_MAX_PATH_SIZE];
|
919 mike 1.1
920 if (0 != FormatLogFileName(uid, gid, path))
921 {
|
922 krisbash 1.3 trace_CannotFormatLogFilename();
|
923 mike 1.1 goto failed;
924 }
925
926 /* Create/open fiel with permisisons 644 */
927 logfd = open(path, O_WRONLY|O_CREAT|O_APPEND, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
928 if (logfd == -1)
929 {
|
930 krisbash 1.3 trace_CreateLogFile_Failed(scs(path), (int)errno);
|
931 mike 1.1 goto failed;
932 }
933 }
934
|
935 krisbash 1.3 agent = (AgentElem*)StrandMany_New(
936 STRAND_DEBUG( AgentElem )
937 &_AgentElem_FT,
938 &_AgentElem_InternalFT,
939 sizeof(AgentElem),
940 STRAND_FLAG_ENTERSTRAND,
941 NULL,
942 100,
943 _AgentElem_HashMapHashProc,
944 _AgentElem_HashMapEqualProc,
945 _AgentElem_FindRequest );
|
946 mike 1.1
947 if (!agent)
948 goto failed;
949
950 agent->agentMgr = self;
951 agent->uid = uid;
952 agent->gid = gid;
953
|
954 krisbash 1.3 if ((agent->agentPID =
|
955 mike 1.1 _SpawnAgentProcess(
|
956 krisbash 1.3 s[0],
957 logfd,
958 uid,
959 gid,
960 self->provDir,
|
961 mike 1.1 (MI_Uint32)(self->provmgr.idleTimeoutUsec / 1000000))) < 0)
962 {
|
963 krisbash 1.3 trace_CannotSpawnChildProcess();
|
964 mike 1.1 goto failed;
965 }
966
967 close(logfd);
968 logfd = -1;
969
970 /* Close socket 0 - it will be used by child process */
971 Sock_Close(s[0]);
972 s[0] = INVALID_SOCK;
973
|
974 krisbash 1.3 Strand_OpenPrepare(&agent->strand.strand,&interactionParams,NULL,NULL,MI_TRUE);
975
976 if( MI_RESULT_OK != ProtocolSocketAndBase_New_AgentConnector(
|
977 mike 1.1 &agent->protocol,
978 self->selector,
979 s[1],
|
980 krisbash 1.3 &interactionParams ) )
|
981 mike 1.1 goto failed;
982
983 s[1] = INVALID_SOCK;
984
|
985 krisbash 1.3 trace_AgentItemCreated(agent);
|
986 mike 1.1 List_Append(
|
987 krisbash 1.3 &self->headAgents,
988 &self->tailAgents,
989 (ListElem*)&(agent->next));
|
990 mike 1.1
991 return agent;
992
993 failed:
|
994 krisbash 1.3 if (INVALID_SOCK != s[0])
|
995 mike 1.1 Sock_Close(s[0]);
996
|
997 krisbash 1.3 if (INVALID_SOCK != s[1])
|
998 mike 1.1 Sock_Close(s[1]);
999
|
1000 krisbash 1.3 if (-1 != logfd)
|
1001 mike 1.1 close(logfd);
1002
1003 if (agent)
|
1004 krisbash 1.3 {
1005 _AgentElem_InitiateClose(agent);
1006 }
|
1007 mike 1.1
1008 return 0;
1009 }
1010
|
1011 krisbash 1.3 // Called with AgentMgr lock acquired
1012 static MI_Result _SendRequestToAgent_Common(
1013 _In_ RequestItem* requestItem,
1014 _In_ Message* msg,
1015 _In_opt_ const ProvRegEntry* proventry)
|
1016 mike 1.1 {
|
1017 krisbash 1.3 MI_Result result;
1018 Message* req = NULL;
1019 MI_Uint64 operationId;
1020
1021 operationId = _NextOperationId();
1022 requestItem->key = operationId;
1023
1024 result = _PrepareMessageForAgent( operationId, msg, &req );
1025 if( MI_RESULT_OK != result )
1026 {
1027 trace_PrepareMessageForAgent_Failed(result);
1028 StrandEntry_DeleteNoAdded( &requestItem->strand );
1029 return result;
1030 }
1031
1032 if( NULL != proventry )
1033 {
1034 DEBUG_ASSERT( Message_IsRequest(req) );
1035 {
1036 RequestMsg* request = (RequestMsg*)req;
1037 request->libraryName = Batch_Strdup(req->batch, proventry->libraryName);
1038 krisbash 1.3 request->instanceLifetimeContext = proventry->instanceLifetimeContext;
1039
1040 if (!request->libraryName)
1041 {
1042 trace_SendRequestToAgent_Batch_Strdup_Failed();
1043 StrandEntry_DeleteNoAdded( &requestItem->strand );
1044 Message_Release(req);
1045 return MI_RESULT_FAILED;
1046 }
1047 }
1048 }
1049
1050 trace_AgentMgr_SendRequestToAgent(
1051 req,
1052 req->tag,
1053 MessageName(req->tag),
1054 req->operationId,
1055 requestItem->originalOperationId,
1056 requestItem->key );
1057
1058 StrandEntry_ScheduleAdd( &requestItem->strand, req);
|
1059 mike 1.1
|
1060 krisbash 1.3 Message_Release(req);
|
1061 mike 1.1
|
1062 krisbash 1.3 return MI_RESULT_OK;
|
1063 mike 1.1 }
1064
|
1065 krisbash 1.3 // Called with AgentMgr lock acquired
1066 static MI_Result _SendIdleRequestToAgent(
1067 _Inout_ AgentElem* agent )
1068 {
1069 RequestItem* requestItem;
1070 MI_Result result;
1071 BinProtocolNotification* notification;
|
1072 mike 1.1
|
1073 krisbash 1.3 notification = BinProtocolNotification_New( BinNotificationAgentIdle );
|
1074 mike 1.1
|
1075 krisbash 1.3 if( !notification )
1076 {
1077 trace_SendRequestToAgent_StrandNewFailed();
|
1078 mike 1.1 return MI_RESULT_FAILED;
|
1079 krisbash 1.3 }
|
1080 mike 1.1
|
1081 krisbash 1.3 requestItem = (RequestItem*) StrandEntry_New(
1082 STRAND_DEBUG( IdleRequestItem )
1083 &agent->strand,
1084 &_IdleRequestItem_FT,
1085 sizeof(RequestItem),
1086 STRAND_FLAG_ENTERSTRAND|STRAND_FLAG_NOINTERACTION,
1087 NULL );
1088 if( NULL == requestItem )
|
1089 mike 1.1 {
|
1090 krisbash 1.3 trace_SendRequestToAgent_StrandNewFailed();
1091 BinProtocolNotification_Release(notification);
|
1092 mike 1.1 return MI_RESULT_FAILED;
1093 }
1094
|
1095 krisbash 1.3 requestItem->isIdleRequest = MI_TRUE;
1096 requestItem->pendingCancel = MI_FALSE;
1097 requestItem->finishOnErrorState = RequestItemFinishState_None;
1098 Strand_SetDelayFinish(&requestItem->strand.strand);
1099 Strand_Leave(&requestItem->strand.strand);
1100
1101 result = _SendRequestToAgent_Common( requestItem, ¬ification->base, NULL );
1102
1103 BinProtocolNotification_Release(notification);
|
1104 mike 1.1
|
1105 krisbash 1.3 return result;
1106 }
1107
1108 // Called with AgentMgr lock acquired
1109 static MI_Result _SendRequestToAgent(
1110 _Inout_ AgentElem* agent,
1111 _In_ InteractionOpenParams* interactionParams,
1112 _In_ Message* msg,
1113 _In_ const ProvRegEntry* proventry)
1114 {
1115 RequestItem* requestItem;
1116
1117 DEBUG_ASSERT( NULL != interactionParams );
1118 trace_SendMessageToAgent( msg->tag );
1119
1120 requestItem = (RequestItem*) StrandEntry_New(
1121 STRAND_DEBUG( RequestItem )
1122 &agent->strand,
1123 &_RequestItem_FT,
1124 sizeof(RequestItem),
1125 0,
1126 krisbash 1.3 interactionParams );
1127 if( NULL == requestItem )
|
1128 mike 1.1 {
|
1129 krisbash 1.3 trace_SendRequestToAgent_StrandNewFailed();
|
1130 mike 1.1 return MI_RESULT_FAILED;
1131 }
|
1132 krisbash 1.3
1133 requestItem->originalOperationId = msg->operationId;
1134 requestItem->request = msg;
1135 requestItem->isIdleRequest = MI_FALSE;
1136 requestItem->pendingCancel = MI_FALSE;
1137 requestItem->finishOnErrorState = RequestItemFinishState_None;
1138
|
1139 mike 1.1 /* Add ref to keep request around until Result received */
1140 Message_AddRef(msg);
1141
|
1142 krisbash 1.3 return _SendRequestToAgent_Common( requestItem, msg, proventry );
|
1143 mike 1.1 }
1144
1145 #endif
1146
1147 /*
1148 **==============================================================================
1149 **
1150 ** Public API
1151 **
1152 **==============================================================================
1153 */
1154 MI_Result AgentMgr_Init(
1155 AgentMgr* self,
1156 Selector* selector)
1157 {
1158 /* Check parameters */
1159 if (!self)
1160 return MI_RESULT_INVALID_PARAMETER;
1161
1162 memset(self, 0, sizeof(*self));
1163
1164 mike 1.1 /* Initialize the provider manager */
|
1165 krisbash 1.3 MI_RETURN_ERR(ProvMgr_Init(&self->provmgr, selector, NULL, NULL, OMI_GetPath(ID_PROVIDERDIR)));
|
1166 mike 1.1
|
1167 krisbash 1.3 self->home = PAL_Strdup(OMI_GetPath(ID_PREFIX));
1168 self->provDir = PAL_Strdup(OMI_GetPath(ID_PROVIDERDIR));
|
1169 mike 1.1
1170 self->selector = selector;
1171
|
1172 krisbash 1.3 ReadWriteLock_Init(&self->lock);
1173
1174 #if defined(CONFIG_ENABLE_PREEXEC)
1175 PreExec_Construct(&self->preexec);
1176 #endif /* defined(CONFIG_ENABLE_PREEXEC) */
1177
|
1178 mike 1.1 return MI_RESULT_OK;
1179 }
1180
1181 MI_Result AgentMgr_Destroy(
1182 AgentMgr* self)
1183 {
|
1184 krisbash 1.3 ListElem* listElem;
1185
|
1186 mike 1.1 ProvMgr_Destroy(&self->provmgr);
|
1187 krisbash 1.3 PAL_Free(self->home);
1188 PAL_Free(self->provDir);
1189
1190 #if defined(CONFIG_ENABLE_PREEXEC)
1191 PreExec_Destruct(&self->preexec);
1192 #endif /* defined(CONFIG_ENABLE_PREEXEC) */
|
1193 mike 1.1
1194 #if defined(CONFIG_POSIX)
1195 /*
1196 Free all outstanding agents
1197 */
|
1198 krisbash 1.3 ReadWriteLock_AcquireWrite(&self->lock);
1199 listElem = self->headAgents;
1200 while (listElem)
|
1201 mike 1.1 {
|
1202 krisbash 1.3 AgentElem* agent = FromOffset(AgentElem,next,listElem);
|
1203 mike 1.1
|
1204 krisbash 1.3 StrandMany_ScheduleAux( &agent->strand, AGENTELEM_STRANDAUX_CLOSEAGENTITEM );
|
1205 mike 1.1
|
1206 krisbash 1.3 listElem = listElem->next;
|
1207 mike 1.1 }
|
1208 krisbash 1.3 ReadWriteLock_ReleaseWrite(&self->lock);
|
1209 mike 1.1 #endif
1210
1211 /* Invalidate self */
1212 memset(self, 0xdd, sizeof(*self));
1213
1214 return MI_RESULT_OK;
1215 }
1216
|
1217 krisbash 1.3 void AgentMgr_OpenCallback(
1218 _Inout_ InteractionOpenParams* params )
1219 {
1220 MI_Result result;
1221 AgentMgr_OpenCallbackData* callbackData = (AgentMgr_OpenCallbackData*)params->callbackData;
1222
1223 result = AgentMgr_HandleRequest( callbackData->self, params, callbackData->proventry );
1224 if( MI_RESULT_OK != result )
1225 {
1226 Strand_FailOpenWithResult(params, result, PostResultMsg_NewAndSerialize);
1227 }
1228 }
1229
|
1230 mike 1.1 MI_Result AgentMgr_HandleRequest(
|
1231 krisbash 1.3 _In_ AgentMgr* self,
1232 _Inout_ InteractionOpenParams* params,
1233 _In_ const ProvRegEntry* proventry)
|
1234 mike 1.1 {
|
1235 krisbash 1.3 MI_Result result = MI_RESULT_OK;
|
1236 mike 1.1 AgentElem* agent;
1237 uid_t uid;
1238 gid_t gid;
|
1239 krisbash 1.3 RequestMsg* msg = (RequestMsg*)params->msg;
1240
1241 trace_AgentMgrHandleRequest(msg, msg->base.tag);
1242
1243 DEBUG_ASSERT( Message_IsRequest(&msg->base) );
|
1244 mike 1.1
1245 if (proventry->hosting == PROV_HOSTING_INPROC)
|
1246 krisbash 1.3 {
1247 #if defined(CONFIG_POSIX)
1248 /* For in proc provider, following checks if an incoming
1249 * request from non-root user, and omiserver is running
1250 * under root user, then return access denied error, otherwise
1251 * it could cause a problem that non-root user runs code under root
1252 */
1253 if (IsAuthCallsIgnored() == 0)
1254 {
1255 /* Reject in-proc provider requests for non-root client users */
1256 if (IsRoot() == 0 && msg->authInfo.uid != 0)
1257 {
1258 /* user name */
1259 char name[USERNAME_SIZE];
1260 char* uname = (char*)name;
1261 if (0 != GetUserName(msg->authInfo.uid, name))
1262 uname = "unknown user";
1263 trace_NonRootUserAccessInprocProvider(uname, proventry->className, proventry->nameSpace);
1264 return MI_RESULT_ACCESS_DENIED;
1265 }
1266 }
1267 krisbash 1.3 #endif /* defined(CONFIG_POSIX) */
1268
1269 return ProvMgr_NewRequest(
|
1270 mike 1.1 &self->provmgr,
|
1271 krisbash 1.3 proventry,
1272 params );
1273 }
|
1274 mike 1.1
1275 if (proventry->hosting == PROV_HOSTING_USER)
1276 {
1277 if (0 != LookupUser(proventry->user, &uid, &gid))
1278 {
|
1279 krisbash 1.3 trace_GetUserUidGid_Failed(scs(proventry->user));
|
1280 mike 1.1 return MI_RESULT_FAILED;
1281 }
1282 }
1283 else
1284 {
|
1285 krisbash 1.3 uid = msg->authInfo.uid;
1286 gid = msg->authInfo.gid;
1287 MI_UNREFERENCED_PARAMETER(uid);
1288 MI_UNREFERENCED_PARAMETER(gid);
|
1289 mike 1.1 }
1290
|
1291 krisbash 1.3 #if defined(CONFIG_ENABLE_PREEXEC)
1292 if (PreExec_Exec(&self->preexec, proventry->preexec, uid, gid) != 0)
1293 return MI_RESULT_FAILED;
1294 #endif /* defined(CONFIG_ENABLE_PREEXEC) */
1295
|
1296 mike 1.1 #if defined(CONFIG_POSIX)
1297
|
1298 krisbash 1.3 // We cannot use ReadWriteLock_AcquireRead(&self->lock);
1299 // as we may need to create the object here
1300 // (and there is no option to upgrade from read to write acquisition)
1301 ReadWriteLock_AcquireWrite(&self->lock);
1302
1303 agent = _FindAgent(self, uid, gid);
|
1304 mike 1.1
1305 if (!agent)
|
1306 krisbash 1.3 {
1307 agent = _CreateAgent(self, uid, gid );
1308
1309 if (!agent)
1310 {
1311 trace_FailedLoadProviderAgent();
1312 result = MI_RESULT_FAILED;
1313 }
1314 else
1315 {
1316 result = _SendIdleRequestToAgent( agent );
1317 }
1318 }
1319
1320 if( MI_RESULT_OK == result )
1321 {
1322 result = _SendRequestToAgent(agent, params, &msg->base, proventry);
1323 }
1324
1325 ReadWriteLock_ReleaseWrite(&self->lock);
1326
1327 krisbash 1.3 return result;
|
1328 mike 1.1
1329 #else
1330 MI_UNUSED(agent);
1331 /* windows version hosts all providers as 'in-proc' */
|
1332 krisbash 1.3 return ProvMgr_NewRequest(
|
1333 mike 1.1 &self->provmgr,
|
1334 krisbash 1.3 proventry,
1335 params );
|
1336 mike 1.1 #endif
1337 }
|