Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

proc_advocate.cc

Go to the documentation of this file.
00001 /*
00002  * proc_advocate.c
00003  *
00004  * Copyright (c) 2003, 2004 The University of Utah and the Flux Group.
00005  * All rights reserved.
00006  *
00007  * This file is licensed under the terms of the GNU Public License.  
00008  * See the file "license.terms" for restrictions on redistribution 
00009  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00010  */
00011 
00012 /**
00013  * @file proc_advocate.cc
00014  *
00015  * Wrapper used to attach unmodified programs to the Broker.
00016  */
00017 
00018 #include "config.h"
00019 
00020 #include <stdlib.h>
00021 #include <string.h>
00022 
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <unistd.h>
00026 
00027 #include <assert_pp.h>
00028 #include <time_util.h>
00029 #include <instrumentation.h>
00030 
00031 #include <iostream>
00032 
00033 #include <rk/rk.h>
00034 #include "rk_util.h"
00035 
00036 #include "BrokerC.h"
00037 #include "RealTimeTaskImpl.hh"
00038 #include "MaxDecayTaskAdvocate.hh"
00039 
00040 using namespace std;
00041 
00042 #define INSTR_proc_len LRTIME_INSTR
00043 #define INSTR_proc_len_data "proc_len", "the wall clock time"
00044 
00045 #if defined(INSTR_proc_len_data)
00046 static struct iPoint INSTR_proc_len_point = {
00047     INSTR_proc_len_data,
00048 };
00049 #endif
00050 
00051 #if defined(INSTR_proc_advocate_periodic_data)
00052 static double periodic_history[1000];
00053 static struct iPoint INSTR_proc_advocate_periodic_point = {
00054     INSTR_proc_advocate_periodic_data,
00055     0,
00056     IPOINT_INIT_HISTORY(periodic_history),
00057 };
00058 #endif
00059 
00060 #if defined(INSTR_proc_advocate_rpc_data)
00061 #undef INSTR_proc_advocate_rpc
00062 #define INSTR_proc_advocate_rpc LRTIME_INSTR
00063 static struct iPoint INSTR_proc_advocate_rpc_point = {
00064     INSTR_proc_advocate_rpc_data,
00065 };
00066 #endif
00067 
00068 #if defined(INSTR_proc_advocate_periods_data)
00069 #undef INSTR_proc_advocate_periods
00070 #define INSTR_proc_advocate_periods LRTIME_INSTR
00071 static double periods_history[1000];
00072 static struct iPoint INSTR_proc_advocate_periods_point = {
00073     INSTR_proc_advocate_periods_data,
00074     0,
00075     IPOINT_INIT_HISTORY(periods_history),
00076 };
00077 #endif
00078 
00079 enum {
00080     PAB_DONE,
00081     PAB_CREATED_RESOURCE_SET,
00082     PAB_NO_OBSERVE,
00083 };
00084 
00085 /*
00086  * Flags for the pa_data.pa_Flags field.
00087  *
00088  * PAF_DONE - Stop monitoring the resource set/child process.
00089  */
00090 enum {
00091     PAF_DONE = (1L << PAB_DONE),
00092     PAF_CREATED_RESOURCE_SET = (1L << PAB_CREATED_RESOURCE_SET),
00093     PAF_NO_OBSERVE = (1L << PAB_NO_OBSERVE),
00094 };
00095 
00096 /*
00097  * Global data for the tool.
00098  *
00099  * pa_Flags - Holds the PAF_ flags.
00100  * pa_ManagerIOR - The IOR of the Broker::Manager object to use.
00101  * pa_TaskIOR - The IOR of the Broker::RealTimeTask object to send reports to.
00102  * pa_TaskName - The name of the task to create.
00103  * pa_ChildPID - The PID of the wrapped process.
00104  * pa_ChildPeriod - The period to use when making reports.
00105  * pa_Advocate - The Broker::RealTimeTask object to send reports to.
00106  * pa_ResourceSet - The resource set for this process and the child.
00107  * pa_LastUsage - The last recorded CPU usage, in microseconds.
00108  */
00109 static struct {
00110     PortableServer::POA_var pa_POA;
00111     unsigned long pa_Flags;
00112     const char *pa_ManagerIOR;
00113     const char *pa_TaskIOR;
00114     const char *pa_TaskName;
00115     pid_t pa_ChildPID;
00116     CORBA::ULong pa_ChildPeriod;
00117     Broker::RealTimeTask_ptr pa_Advocate;
00118     rk_resource_set_t pa_ResourceSet;
00119     unsigned long long pa_LastUsage;
00120     Broker::KeyedReportParameters pa_KeyedReportParameters;
00121 } pa_data;
00122 
00123 /**
00124  * Handle a SIGCHLD signal.  This function will be called when the child exits.
00125  *
00126  * @param sig The actual signal number received.
00127  */
00128 static void sigchld(int sig)
00129 {
00130     require(sig == SIGCHLD);
00131     
00132     pa_data.pa_Flags |= PAF_DONE;
00133 }
00134 
00135 /**
00136  * A signal handler that passes the received signal on to the child process.
00137  *
00138  * @param sig The actual signal number received.
00139  */
00140 static void sigpass(int sig)
00141 {
00142     require(pa_data.pa_ChildPID > 0);
00143     require((sig == SIGINT) || (sig == SIGTERM));
00144     
00145     kill(pa_data.pa_ChildPID, sig);
00146 }
00147 
00148 /**
00149  * The SIGALRM signal handler.  This function will be called at the end of
00150  * every period to report CPU usage to the advocate.
00151  *
00152  * @param sig The actual signal number received.
00153  */
00154 static void sigalrm(int sig)
00155 {
00156     struct rk_resource_set_usage rsu;
00157     int rc;
00158 
00159     require(pa_data.pa_ResourceSet != NULL_RESOURCE_SET);
00160     require(!CORBA::is_nil(pa_data.pa_Advocate));
00161     require(sig == SIGALRM);
00162 
00163     INSTR_proc_advocate_periods(&INSTR_proc_advocate_periods_point, {
00164         memset(&rsu, 0, sizeof(rsu));
00165         if( (rc = rk_resource_set_get_usage(pa_data.pa_ResourceSet,
00166                                             &rsu,
00167                                             NULL)) == 0 )
00168         {
00169             try
00170             {
00171                 Broker::CPUReserve status;
00172 
00173                 status.Period = pa_data.pa_ChildPeriod;
00174                 status.Compute = (CORBA::ULong)
00175                     (rsu.active_cpu_usage - pa_data.pa_LastUsage);
00176                 pa_data.pa_LastUsage = rsu.active_cpu_usage;
00177                 pa_data.pa_Advocate->
00178                     ReportCPU(status,
00179                               status,
00180                               pa_data.pa_KeyedReportParameters);
00181             }
00182             catch(const CORBA::SystemException &e)
00183             {
00184                 cerr << "System exception: " << e << endl;
00185                 pa_data.pa_Flags |= PAF_DONE;
00186             }
00187             catch(...)
00188             {
00189                 cerr << "Caught unknown exception..." << endl;
00190                 pa_data.pa_Flags |= PAF_DONE;
00191             }
00192         }
00193         else
00194         {
00195             cerr << "rk_resource_set_get_usage: "
00196                  << strerror(rc)
00197                  << endl;
00198             pa_data.pa_Flags |= PAF_DONE;
00199         }
00200     });
00201 }
00202 
00203 /**
00204  * Print out the usage statement to standard error.
00205  *
00206  * @param prog_name The program name.
00207  */
00208 static void paUsage(const char *prog_name)
00209 {
00210     require(pa_data.pa_ManagerIOR != NULL);
00211     require(prog_name != NULL);
00212 
00213     cerr << "CPU Broker wrapper for managing unmodified programs.\n"
00214          << "Usage: "
00215          << prog_name
00216          << " [options] -- <command> [argument ...]\n"
00217          << endl
00218          << "Options:\n"
00219          << "\t-h\t\tThis help message.\n"
00220          << "\t-V\t\tShow the version number.\n"
00221 
00222          << "\t-o\t\tDo not observe the child process or make reports." << endl
00223 
00224          << "\t-m <ior>\tThe Broker::Manager IOR."
00225          << " (Default: " << pa_data.pa_ManagerIOR << ")\n"
00226 
00227          << "\t-t <ior>\tThe Broker::RealTimeTask IOR.\n"
00228 
00229          << "\t-n <name>\tThe name for the task to create.\n"
00230 
00231          << "\t-P <period>\tThe period as a time value."
00232          << " (Default: " << pa_data.pa_ChildPeriod << "us)\n"
00233 
00234          << endl
00235         
00236          << "Package: " << PACKAGE_STRING << endl
00237          << "Contact: " << PACKAGE_BUGREPORT << endl
00238 
00239         ;
00240 }
00241 
00242 /**
00243  * Process the command line options.
00244  *
00245  * @param argc_inout Reference to main's argc variable.  On return, the
00246  * variable will contain the number of arguments remaining after option
00247  * processing.
00248  * @param argv_inout Reference to main's argv variable.  On return, the
00249  * variable will contain the remaining argument values.
00250  * @return True if the options were processed correctly, false otherwise.
00251  */
00252 static int paProcessOptions(int &argc_inout, char **&argv_inout)
00253 {
00254     int ch, retval = 0;
00255     char *prog_name;
00256     char **argv;
00257     int argc;
00258 
00259     argc = argc_inout;
00260     argv = argv_inout;
00261     prog_name = argv[0];
00262     while( ((ch = getopt(argc, argv, "hVn:m:t:P:o")) != -1) && (retval == 0) )
00263     {
00264         switch( ch )
00265         {
00266         case 'm':
00267             if( strlen(optarg) == 0 )
00268             {
00269                 cerr << prog_name << ": Manager IOR is empty" << endl;
00270                 retval = 1;
00271             }
00272             else
00273             {
00274                 pa_data.pa_ManagerIOR = optarg;
00275             }
00276             break;
00277         case 't':
00278             if( strlen(optarg) == 0 )
00279             {
00280                 cerr << prog_name << ": Task IOR is empty" << endl;
00281                 retval = 1;
00282             }
00283             else if( pa_data.pa_TaskName != NULL )
00284             {
00285                 cerr << prog_name
00286                      << ": The -t and -n options are mutually exclusive"
00287                      << endl;
00288                 retval = 1;
00289             }
00290             else
00291             {
00292                 pa_data.pa_TaskIOR = optarg;
00293             }
00294             break;
00295         case 'n':
00296             if( strlen(optarg) == 0 )
00297             {
00298                 cerr << prog_name << ": Task name is empty" << endl;
00299                 retval = 1;
00300             }
00301             else if( pa_data.pa_TaskIOR != NULL )
00302             {
00303                 cerr << prog_name
00304                      << ": The -t and -n options are mutually exclusive"
00305                      << endl;
00306                 retval = 1;
00307             }
00308             else
00309             {
00310                 pa_data.pa_TaskName = optarg;
00311             }
00312             break;
00313         case 'o':
00314             pa_data.pa_Flags |= PAF_NO_OBSERVE;
00315             break;
00316         case 'P':
00317             {
00318                 unsigned long long usecs;
00319                 
00320                 /* Period for the CPU reservation. */
00321                 if( string_to_microsec(&usecs, optarg) )
00322                 {
00323                     pa_data.pa_ChildPeriod = usecs;
00324                 }
00325                 else
00326                 {
00327                     cerr << prog_name
00328                          << ": -P options requires a time value\n";
00329                     retval = 1;
00330                 }
00331             }
00332             break;
00333         case 'V':
00334             cerr << PACKAGE_VERSION << endl;
00335             retval = -1;
00336             break;
00337         case 'h':
00338         case '?':
00339         default:
00340             retval = 1;
00341             break;
00342         }
00343     }
00344 
00345     if( (pa_data.pa_TaskIOR == NULL) && (pa_data.pa_TaskName == NULL) )
00346     {
00347         cerr << prog_name
00348              << ": no task name or IOR specified\n";
00349         retval = 1;
00350     }
00351     
00352     argc_inout -= optind;
00353     argv_inout += optind;
00354     /* Optionally skip the '--' that is used to terminate the option list. */
00355     if( (argc_inout > 0) && (strcmp(argv_inout[0], "--") == 0) )
00356     {
00357         argc_inout -= 1;
00358         argv_inout += 1;
00359     }
00360     return( retval );
00361 }
00362 
00363 /**
00364  * Create the advocate and begin CPU scheduling based on the command line
00365  * parameters.
00366  *
00367  * @param orb Pointer to the ORB instance.
00368  * @param manager The manager for this machine.
00369  * @param task_ior The IOR of the Broker::RealTimeTask to use or NULL if a
00370  * task should be created.
00371  * @param task_name The name of the Broker::RealTimeTask to create or NULL if
00372  * an existing task should be used.
00373  * @return A pointer to the allocated advocate.
00374  */
00375 static Broker::RealTimeTask_ptr paGetAdvocate(CORBA::ORB_ptr orb,
00376                                               Broker::Manager_ptr manager,
00377                                               const char *task_ior,
00378                                               const char *task_name)
00379 {
00380     Broker::RealTimeTask_var retval;
00381     CORBA::Object_var obj;
00382 
00383     require(!CORBA::is_nil(orb));
00384     require(!CORBA::is_nil(manager));
00385     require((task_ior != NULL) || (task_name != NULL));
00386 
00387     if( task_ior != NULL )
00388     {
00389         obj = orb->string_to_object(task_ior);
00390         retval = Broker::RealTimeTask::_narrow(obj.in());
00391         if( CORBA::is_nil(retval.in()) )
00392         {
00393             cerr << "Invalid task factory IOR: "
00394                  << task_ior
00395                  << endl;
00396             throw CORBA::BAD_PARAM();
00397         }
00398         pa_data.pa_TaskName = retval->Name();
00399     }
00400     else if( task_name != NULL )
00401     {
00402         try
00403         {
00404             PortableServer::ObjectId_var oid;
00405             Broker::RealTimeTask_var rtt;
00406             MaxDecayTaskAdvocate *mdta;
00407             Broker::TaskParameters tp;
00408             RealTimeTaskImpl *rtti;
00409             CORBA::Any value;
00410             
00411             tp.length(1);
00412             tp[0].name = "name";
00413             tp[0].value <<= task_name;
00414             rtti = new RealTimeTaskImpl(tp);
00415             oid = pa_data.pa_POA->activate_object(rtti);
00416             rtt = Broker::RealTimeTask::
00417                 _narrow(pa_data.pa_POA->id_to_reference(oid.in()));
00418             mdta = new MaxDecayTaskAdvocate();
00419             value <<= rtt.in();
00420             mdta->SetDelegateAttribute("remote-object", value);
00421             oid = pa_data.pa_POA->activate_object(mdta);
00422             retval = Broker::RealTimeTask::
00423                 _narrow(pa_data.pa_POA->id_to_reference(oid.in()));
00424         }
00425         catch(const Broker::DuplicateTaskParameter &e)
00426         {
00427             cerr << e << endl;
00428             ensure(0);
00429         }
00430         catch(const Broker::InvalidTaskParameter &e)
00431         {
00432             cerr << e << endl;
00433             ensure(0);
00434         }
00435         catch(const Broker::MissingTaskParameter &e)
00436         {
00437             cerr << e << endl;
00438             ensure(0);
00439         }
00440     }
00441     else
00442     {
00443         ensure(0);
00444     }
00445 
00446     if( (pa_data.pa_ResourceSet = rk_proc_get_rset(getpid())) !=
00447         NULL_RESOURCE_SET )
00448     {
00449     }
00450     else if( (pa_data.pa_ResourceSet =
00451               rk_resource_set_get_by_name(pa_data.pa_TaskName)) !=
00452              NULL_RESOURCE_SET )
00453     {
00454     }
00455     else if( (pa_data.pa_ResourceSet =
00456               rk_resource_set_create((char *)pa_data.pa_TaskName)) ==
00457              NULL_RESOURCE_SET )
00458     {
00459         cerr << "rk_resource_set_create: " << strerror(errno) << endl;
00460     }
00461     else
00462     {
00463         pa_data.pa_Flags |= PAF_CREATED_RESOURCE_SET;
00464     }
00465     
00466     try
00467     {
00468         struct rk_resource_set_usage rsu;
00469         Broker::ScheduleParameters sp;
00470 
00471         memset(&rsu, 0, sizeof(rsu));
00472         sp.length(2);
00473         sp[0].name = "period";
00474         sp[0].value <<= pa_data.pa_ChildPeriod;
00475         sp[1].name = "pid";
00476         sp[1].value <<= (CORBA::Long)getpid();
00477         manager->AddTask(retval.in(), sp);
00478         if( rk_resource_set_get_usage(pa_data.pa_ResourceSet,
00479                                       &rsu,
00480                                       NULL) == 0 )
00481         {
00482             pa_data.pa_LastUsage = rsu.active_cpu_usage;
00483         }
00484     }
00485     catch(const Broker::DuplicateScheduleParameter &e)
00486     {
00487         cerr << e << endl;
00488         cerr << e.name << endl;
00489         throw CORBA::UNKNOWN();
00490     }
00491     catch(const Broker::InvalidScheduleParameter &e)
00492     {
00493         cerr << e << endl;
00494         cerr << e.message << endl;
00495         throw CORBA::UNKNOWN();
00496     }
00497     catch(const Broker::MissingScheduleParameter &e)
00498     {
00499         cerr << e << endl;
00500         cerr << e.name << endl;
00501         throw CORBA::UNKNOWN();
00502     }
00503     
00504     return( retval._retn() );
00505 }
00506 
00507 /**
00508  * The parent portion of the fork(2) between pa and the monitored utility.
00509  * This function will attach itself to a resource set to ensure that it has
00510  * some CPU time to work and then wait for gkrellm connections or the child's
00511  * death.
00512  *
00513  * @param rtt The Broker::RealTimeTask that is managing this process.
00514  * @return The return code for main().
00515  *
00516  * @sa paChildPart
00517  */
00518 static int paParentPart(Broker::RealTimeTask_ptr rtt)
00519 {
00520     int retval = EXIT_FAILURE;
00521     struct itimerval itv;
00522     struct sigaction sa;
00523     sigset_t sigmask;
00524 
00525     require(pa_data.pa_ChildPID > 0);
00526     require(!CORBA::is_nil(rtt));
00527     
00528     /*
00529      * We use signals as a primitive event system, so any that we use and are
00530      * not passed on to the child need to be blocked before setting up the
00531      * handlers.  Once everything has been setup, we will use sigsuspend(2) to
00532      * atomically unblock and wait for the signals to arrive.
00533      */
00534     sigemptyset(&sigmask);
00535     sigaddset(&sigmask, SIGALRM);
00536     sigaddset(&sigmask, SIGCHLD);
00537     sigaddset(&sigmask, SIGINT);
00538     sigaddset(&sigmask, SIGTERM);
00539     if( sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0 )
00540     {
00541         perror("sigprocmask");
00542 
00543         ensure(0);
00544     }
00545 
00546     /* Setup the signal handlers. */
00547     sa.sa_mask = sigmask;
00548     sa.sa_flags = 0;
00549 #if defined(SA_RESTART)
00550     sa.sa_flags |= SA_RESTART;
00551 #endif
00552 
00553     if( !(pa_data.pa_Flags & PAF_NO_OBSERVE) )
00554     {
00555         sa.sa_handler = sigalrm;
00556         if( sigaction(SIGALRM, &sa, NULL) < 0 )
00557         {
00558             perror("sigprocmask");
00559             
00560             ensure(0);
00561         }
00562     }
00563 
00564     /* Catch SIGCHLD so we exit with the child. */
00565     sa.sa_handler = sigchld;
00566     if( sigaction(SIGCHLD, &sa, NULL) < 0 )
00567     {
00568         perror("sigprocmask");
00569 
00570         ensure(0);
00571     }
00572     
00573     /*
00574      * Pass SIGINT/SIGTERM onto the child so they can handle them as they
00575      * choose.  If they exit, we will get the SIGCHLD and exit shortly
00576      * thereafter.
00577      */
00578     sa.sa_handler = sigpass;
00579     if( (sigaction(SIGINT, &sa, NULL) < 0) ||
00580         (sigaction(SIGTERM, &sa, NULL) < 0) )
00581     {
00582         perror("sigprocmask");
00583 
00584         ensure(0);
00585     }
00586     
00587     itv.it_interval.tv_sec = 0;
00588     itv.it_interval.tv_usec = pa_data.pa_ChildPeriod;
00589     itv.it_value.tv_sec = 0;
00590     itv.it_value.tv_usec = pa_data.pa_ChildPeriod;
00591     /** @todo Use rk periodic stuff here. */
00592     if( !(pa_data.pa_Flags & PAF_NO_OBSERVE) &&
00593         (setitimer(ITIMER_REAL, &itv, NULL) == -1) )
00594     {
00595         perror("setitimer");
00596         retval = EXIT_FAILURE;
00597     }
00598     else
00599     {
00600         sigset_t empty_sigmask;
00601         int status;
00602 
00603         sigemptyset(&empty_sigmask);
00604 
00605         pa_data.pa_Advocate = rtt;
00606         
00607         /* Keep handling signals until the child has died. */
00608         while( !(pa_data.pa_Flags & PAF_DONE) )
00609         {
00610             INSTR_proc_len(&INSTR_proc_len_point, {
00611             INSTR_proc_advocate_periodic(&INSTR_proc_advocate_periodic_point, {
00612                 sigsuspend(&empty_sigmask);
00613             });
00614             });
00615         }
00616         
00617         pa_data.pa_Advocate = NULL;
00618         
00619         /* Cleanup the child's status. */
00620         if( wait(&status) >= 0 )
00621         {
00622             if( WIFEXITED(status) )
00623             {
00624                 retval = WEXITSTATUS(status);
00625             }
00626             else if( WIFSIGNALED(status) )
00627             {
00628                 retval = EXIT_SUCCESS;
00629             }
00630             else
00631             {
00632                 retval = EXIT_FAILURE;
00633             }
00634         }
00635         else
00636         {
00637             perror("wait");
00638             retval = EXIT_FAILURE;
00639         }
00640         
00641         /* Clear the timer. */
00642         memset(&itv, 0, sizeof(itv));
00643         if( setitimer(ITIMER_REAL, &itv, NULL) < 0 )
00644         {
00645             perror("setitimer");
00646         }
00647     }
00648 
00649     /* We will be dying soon, ignore any signals and */
00650     signal(SIGALRM, SIG_IGN);
00651     signal(SIGCHLD, SIG_IGN);
00652     signal(SIGINT, SIG_IGN);
00653     signal(SIGTERM, SIG_IGN);
00654 
00655     /* ... restore the old signal mask. */
00656     if( sigprocmask(SIG_UNBLOCK, &sigmask, NULL) < 0 )
00657     {
00658         perror("sigprocmask");
00659         
00660         ensure(0);
00661     }
00662     
00663     return( retval );
00664 }
00665 
00666 /**
00667  * The child portion of the fork(2) between the proc_advocate and the monitored
00668  * utility.  This function will execvp(3) the utility with the given arguments.
00669  *
00670  * @param argv The utility to startup and its arguments.
00671  * @return A failure exit code, otherwise this function will not return because
00672  * of the execvp(3).
00673  *
00674  * @sa paParentPart
00675  */
00676 static int paChildPart(char *argv[])
00677 {
00678     int retval = EXIT_SUCCESS;
00679     sigset_t sigmask;
00680 
00681     /* Reset the signal mask for the child. */
00682     sigfillset(&sigmask);
00683     if( sigprocmask(SIG_UNBLOCK, &sigmask, NULL) < 0 )
00684     {
00685         perror("sigprocmask");
00686         
00687         ensure(0);
00688     }
00689 
00690     execvp(argv[0], argv);
00691     
00692     /* FALLTHROUGH, normal operation will not reach this point. */
00693     perror(argv[0]);
00694     switch( errno )
00695     {
00696     case ENOENT:
00697     case EPERM:
00698         retval = 127;
00699         break;
00700     default:
00701         retval = EXIT_FAILURE;
00702         break;
00703     }
00704     return( retval );
00705 }
00706 
00707 int main(int argc, char *argv[])
00708 {
00709     int lpc, old_argc = argc, retval = EXIT_FAILURE;
00710     const char *prog_name = argv[0];
00711 
00712     /* Default values. */
00713     pa_data.pa_ManagerIOR = "file://manager.ior";
00714     pa_data.pa_ChildPeriod = 33333;
00715 
00716     atexit(iPrintPointsAtExit);
00717     
00718     /*
00719      * Change the argc to not include the wrappee's arguments, otherwise,
00720      * our call to ORB_init could consume the wrappee's ORB arguments.
00721      */
00722     for( lpc = 0; (lpc < argc) && (strcmp(argv[lpc], "--") != 0); lpc++ );
00723 
00724     if( lpc < argc )
00725     {
00726         argc = lpc;
00727     }
00728     
00729     try
00730     {
00731         CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
00732         int rc;
00733 
00734         for( ; lpc < old_argc; argc++, lpc++ )
00735         {
00736             argv[argc] = argv[lpc];
00737         }
00738         argv[argc] = NULL;
00739 
00740         rc = paProcessOptions(argc, argv);
00741         
00742         if( pa_data.pa_TaskIOR == NULL )
00743         {
00744             CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
00745             
00746             PortableServer::POA_var root_poa =
00747                 PortableServer::POA::_narrow(obj.in());
00748             PortableServer::POAManager_var mgr = root_poa->the_POAManager();
00749             
00750             PortableServer::ThreadPolicy_var thread = root_poa->
00751                 create_thread_policy(PortableServer::SINGLE_THREAD_MODEL);
00752             
00753             CORBA::PolicyList policy_list;
00754             policy_list.length(1);
00755             policy_list[0] =
00756                 PortableServer::ThreadPolicy::_duplicate(thread.in());
00757             
00758             pa_data.pa_POA = root_poa->
00759                 create_POA("SingleThread", mgr.in(), policy_list);
00760             
00761             thread->destroy();
00762             thread = PortableServer::ThreadPolicy::_nil();
00763             
00764             mgr->activate();
00765         }
00766         
00767         if( (rc == 0) && (argc > 0) )
00768         {
00769             Broker::RealTimeTask_var rtt;
00770             Broker::Manager_var manager;
00771             CORBA::Object_var obj;
00772 
00773             obj = orb->string_to_object(pa_data.pa_ManagerIOR);
00774             manager = Broker::Manager::_narrow(obj.in());
00775             if( CORBA::is_nil(manager.in()) )
00776             {
00777                 cerr << "Invalid manager IOR: "
00778                      << pa_data.pa_ManagerIOR
00779                      << endl;
00780                 throw CORBA::BAD_PARAM();
00781             }
00782 
00783             /*
00784              * Block signals so we do not die without removing ourself from the
00785              * manager.
00786              */
00787             {
00788                 sigset_t sigmask;
00789                 
00790                 sigaddset(&sigmask, SIGINT);
00791                 sigaddset(&sigmask, SIGTERM);
00792                 if( sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0 )
00793                 {
00794                     perror("sigprocmask");
00795                     
00796                     ensure(0);
00797                 }
00798             }
00799             
00800             rtt = paGetAdvocate(orb.in(),
00801                                 manager.in(),
00802                                 pa_data.pa_TaskIOR,
00803                                 pa_data.pa_TaskName);
00804             if( (pa_data.pa_ChildPID = fork()) > 0 )
00805             {
00806                 retval = paParentPart(rtt.in());
00807             }
00808             else if( pa_data.pa_ChildPID == 0 )
00809             {
00810                 return( paChildPart(argv) );
00811             }
00812             else
00813             {
00814                 /* The fork failed. */
00815                 retval = EXIT_FAILURE;
00816             }
00817             manager->RemoveTask(rtt.in());
00818         }
00819         else
00820         {
00821             if( rc == 0 )
00822             {
00823                 cerr << "No utility to execute\n";
00824             }
00825             if( rc >= 0 )
00826             {
00827                 paUsage(prog_name);
00828             }
00829         }
00830     }
00831     catch(const CORBA::UNKNOWN &e)
00832     {
00833         // Ignore...
00834         paUsage(prog_name);
00835     }
00836     catch(const CORBA::SystemException &e)
00837     {
00838         cerr << "Caught Exception: " << e << endl;
00839     }
00840     catch(...)
00841     {
00842         cerr << "Caught an unhandled exception" << endl;
00843     }
00844 
00845     if( pa_data.pa_Flags & PAF_CREATED_RESOURCE_SET )
00846     {
00847         rk_resource_set_destroy(pa_data.pa_ResourceSet);
00848         pa_data.pa_ResourceSet = NULL_RESOURCE_SET;
00849     }
00850     
00851     return( retval );
00852 }

Generated on Fri Oct 22 07:50:24 2004 for CPU Broker by  doxygen 1.3.9.1