• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 9959853035

16 Jul 2024 03:34PM UTC coverage: 55.893% (+0.009%) from 55.884%
9959853035

push

github

web-flow
Fix for assigning to non-existent variables (#1708) (#1718)

* Fix for assigning to non-existent variables (#1708)

This fix modifies Trick's convert_swig script.  It
adds a directive to not accept dynamic attributes.
The directive will ensure that modelers do not
assign to non-existent parameter in their input files.

The prior fix (issues #1288 and/or #1603) did not
cover C structures, so this commit is really an
addendum to that fix.  With this commit, the convert_swig
script will generate a non-dynamic directive foreach
class and structure.

This fix also stops generating swig interface code
for typedef structure definitions since swig only
produces an interface to the actual typedef name.
For example, with this typedef:

typedef struct StructureName {
   double  main_engine_thrust;  /* N Thrust of main engine */
   struct StructureName* next;  /* ** Next pointer */
} TypeDefName;

swig creates an interface for "TypeDefName", and not
"StructureName", so there is no need for Trick to
produce anything in regards "StructureName".

* Fix for issue with classes defined in ifndef SWIG block

convert_swig takes in the raw header and does no preprocessing,
so blocks of c/c++ header code which are meant to be skipped
by Swig are processed by convert_swig.  This causes an issue
with the generated python code that try to access classes
that are ifndef SWIGed out.

To fix this, check for class existence in the generated python
code e.g:

if 'MomMom' in globals():
    MomMom.__setattr__ = _swig_setattr_nondynamic_instance_variable(object.__setattr__)

* Fix for assignment to swig_double and swig_int primitives

The previous commit(s) on this branch fixed bad assignments
like (misspell position an attribute of BSTATE_IN):
ball.state.input.positiaaaan = 4.0

This commit fixes bad assignments to leaf/primitive attributes
like (try to add attribute to primitive/leaf double type):

ball.state.input.position.fred = 4... (continued)

12292 of 21992 relevant lines covered (55.89%)

73526.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.04
/trick_source/sim_services/Executive/Threads_child.cpp
1
/*
2
   PURPOSE: (The Trick simulation child executive processing.)
3

4
   REFERENCE: ((None))
5

6
   ASSUMPTIONS AND LIMITATIONS: ((this is executive only from the child process forked by the executive))
7

8
   PROGRAMMERS:
9
      (((Robert W. Bailey) (LinCom) (October 1993) (--) (Realtime))
10
       ((Eddie J. Paddock) (MDSSC) (April 1992) (--) (Realtime)))
11
 */
12

13
#include <iostream>
14
#include <stdlib.h>
15
#include <errno.h>
16
#include <signal.h>
17
#include <sys/syscall.h>
18

19
#ifdef __linux
20
#include <cxxabi.h>
21
#endif
22

23
#include "trick/Threads.hh"
24
#include "trick/release.h"
25
#include "trick/ExecutiveException.hh"
26
#include "trick/exec_proto.h"
27
#include "trick/TrickConstant.hh"
28
#include "trick/message_proto.h"
29

30

31
/**
32
@details
33
-# Wait for all job dependencies to complete.  Requirement  [@ref r_exec_thread_6]
34
-# Call the job.  Requirement  [@ref r_exec_periodic_0]
35
-# If the job is a system job, check to see if the next job call time is the lowest next time by
36
   calling Trick::ScheduledJobQueue::test_next_job_call_time(Trick::JobData *, long long)
37
-# Set the job complete flag
38
*/
39
static int call_next_job(Trick::JobData * curr_job, Trick::ScheduledJobQueue & job_queue, bool rt_nap, long long curr_time_tics) {
555✔
40

41
    Trick::JobData * depend_job ;
42
    unsigned int ii ;
43
    int ret = 0 ;
555✔
44

45
    //cout << "time = " << curr_time_tics << " " << curr_job->name << " job next = "
46
    //  << curr_job->next_tics << " id = " << curr_job->id << endl ;
47

48
    /* Wait for all jobs that the current job depends on to complete. */
49
    for ( ii = 0 ; ii < curr_job->depends.size() ; ii++ ) {
793✔
50
        depend_job = curr_job->depends[ii] ;
238✔
51
        while (! depend_job->complete) {
354✔
52
            if (rt_nap == true) {
116✔
53
                RELEASE();
116✔
54
            }
55
        }
56
    }
57

58
    /* Call the current scheduled job. */
59
    ret = curr_job->call() ;
556✔
60

61
    if ( ret != 0 ) {
556✔
62
        exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , "scheduled job did not return 0") ;
×
63
    }
64

65
    /* System jobs next call time are not set until after they run. We test their next job call time here. */
66
    if ( curr_job->system_job_class ) {
556✔
67
        job_queue.test_next_job_call_time(curr_job , curr_time_tics) ;
5✔
68
    }
69

70
    curr_job->complete = true ;
556✔
71

72
    return 0 ;
556✔
73
}
74

75
/**
76
@details
77
-# Block all signals to the child.
78
-# Set the thread cancel type to asynchronous to allow master to this child at any time.
79
-# Lock the go mutex so the master has to wait until this child is ready before staring execution.
80
-# Set thread priority and CPU affinity
81
-# The child enters an infinite loop
82
    -# Blocks on mutex or frame trigger until master signals to start processing
83
    -# Switch if the child is a synchronous thread
84
        -# For each scheduled jobs whose next call time is equal to the current simulation time [@ref ScheduledJobQueue]
85
            -# Call call_next_job(Trick::JobData * curr_job, Trick::ScheduledJobQueue & job_queue, bool rt_nap, long long curr_time_tics)
86
    -# Switch if the child is a asynchronous must finish thread
87
        -# Do while the job queue time is less than the time of the next AMF sync time.
88
            -# For each scheduled jobs whose next call time is equal to the current queue time
89
                -# Call call_next_job(Trick::JobData * curr_job, Trick::ScheduledJobQueue & job_queue, bool rt_nap, long long curr_time_tics)
90
    -# Switch if the child is a asynchronous thread
91
        -# For each scheduled jobs
92
            -# Call call_next_job(Trick::JobData * curr_job, Trick::ScheduledJobQueue & job_queue, bool rt_nap, long long curr_time_tics)
93
    -# Set the child complete flag
94
*/
95
void * Trick::Threads::thread_body() {
5✔
96

97
    /* Lock the go mutex so the master has to wait until this child is ready before staring execution. */
98
    trigger_container.getThreadTrigger()->init() ;
5✔
99

100
    /* signal the master that the child is ready and running */
101
    child_complete = true;
5✔
102
    running = true ;
5✔
103

104
    try {
105
        do {
106

107
            /* Block child on trigger until master signals. */
108
            trigger_container.getThreadTrigger()->wait() ;
1,434✔
109

110
            if ( enabled ) {
1,430✔
111

112
                switch ( process_type ) {
1,430✔
113
                    case PROCESS_TYPE_SCHEDULED:
1,001✔
114
                    /* Loop through all jobs currently scheduled to run at this simulation time step. */
115
                    job_queue.reset_curr_index() ;
1,001✔
116
                    job_queue.set_next_job_call_time(TRICK_MAX_LONG_LONG) ;
1,001✔
117
                    while ( (curr_job = job_queue.find_next_job( curr_time_tics )) != NULL ) {
1,114✔
118
                        call_next_job(curr_job, job_queue, rt_nap, curr_time_tics) ;
113✔
119
                    }
120
                    break ;
1,001✔
121

122
                    case PROCESS_TYPE_AMF_CHILD:
428✔
123
                    /* call the AMF top of frame jobs */
124
                    top_of_frame_queue.reset_curr_index() ;
428✔
125
                    while ( (curr_job = top_of_frame_queue.get_next_job()) != NULL ) {
1,277✔
126
                        int ret ;
127
                        ret = curr_job->call() ;
856✔
128
                        if ( ret != 0 ) {
850✔
129
                            exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , " top_of_frame job did not return 0") ;
×
130
                        }
131
                    }
132

133
                    /* Loop through all jobs currently up to the point of the next AMF frame sync */
134
                    do {
×
135
                        job_queue.reset_curr_index() ;
422✔
136
                        job_queue.set_next_job_call_time(amf_next_tics) ;
424✔
137
                        while ( (curr_job = job_queue.find_next_job( curr_time_tics )) != NULL ) {
864✔
138
                            call_next_job(curr_job, job_queue, rt_nap, curr_time_tics) ;
441✔
139
                        }
140
                        curr_time_tics = job_queue.get_next_job_call_time() ;
427✔
141
                    } while ( curr_time_tics < amf_next_tics ) ;
428✔
142

143
                    /* call the AMF end of frame jobs */
144
                    end_of_frame_queue.reset_curr_index() ;
428✔
145
                    while ( (curr_job = end_of_frame_queue.get_next_job()) != NULL ) {
428✔
146
                        int ret ;
147
                        ret = curr_job->call() ;
×
148
                        if ( ret != 0 ) {
×
149
                            exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , " end_of_frame job did not return 0") ;
×
150
                        }
151
                    }
152
                    break ;
428✔
153

154
                    case PROCESS_TYPE_ASYNC_CHILD:
1✔
155
                    /* Loop through all jobs once */
156
                    if ( amf_cycle_tics == 0 ) {
1✔
157
                        // Old behavior, run all jobs once and return.
158
                        job_queue.reset_curr_index() ;
1✔
159
                        job_queue.set_next_job_call_time(TRICK_MAX_LONG_LONG) ;
1✔
160
                        while ( (curr_job = job_queue.get_next_job()) != NULL ) {
2✔
161
                            call_next_job(curr_job, job_queue, rt_nap, curr_time_tics) ;
2✔
162
                        }
163
                    } else {
164

165
                        // catch up job next times to current frame.
166
                        job_queue.reset_curr_index() ;
×
167
                        while ( (curr_job = job_queue.get_next_job()) != NULL ) {
×
168
                            long long start_frame = amf_next_tics - amf_cycle_tics ;
×
169
                            while ( curr_job->next_tics < start_frame ) {
×
170
                                curr_job->next_tics += curr_job->cycle_tics ;
×
171
                            }
172
                        }
173

174
                        // New behavior, run a mini scheduler.
175
                        /* call the AMF top of frame jobs */
176
                        top_of_frame_queue.reset_curr_index() ;
×
177
                        while ( (curr_job = top_of_frame_queue.get_next_job()) != NULL ) {
×
178
                            int ret ;
179
                            ret = curr_job->call() ;
×
180
                            if ( ret != 0 ) {
×
181
                                exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , " top_of_frame job did not return 0") ;
×
182
                            }
183
                        }
184

185
                        /* Loop through all jobs currently up to the point of the next AMF frame sync */
186
                        do {
×
187
                            job_queue.reset_curr_index() ;
×
188
                            job_queue.set_next_job_call_time(amf_next_tics) ;
×
189
                            while ( (curr_job = job_queue.find_next_job( curr_time_tics )) != NULL ) {
×
190
                                call_next_job(curr_job, job_queue, rt_nap, curr_time_tics) ;
×
191
                            }
192
                            curr_time_tics = job_queue.get_next_job_call_time() ;
×
193
                        } while ( curr_time_tics < amf_next_tics ) ;
×
194

195
                        /* call the AMF end of frame jobs */
196
                        end_of_frame_queue.reset_curr_index() ;
×
197
                        while ( (curr_job = end_of_frame_queue.get_next_job()) != NULL ) {
×
198
                            int ret ;
199
                            ret = curr_job->call() ;
×
200
                            if ( ret != 0 ) {
×
201
                                exec_terminate_with_return(ret , curr_job->name.c_str() , 0 , " end_of_frame job did not return 0") ;
×
202
                            }
203
                        }
204
                    }
205
                    break ;
×
206

207
                    default:
×
208
                    break ;
×
209
                }
210
            }
211

212
            /* After all jobs have completed, set the child_complete flag to true. */
213
            child_complete = true;
1,429✔
214

215
        } while (1);
216
    } catch (Trick::ExecutiveException & ex ) {
×
217
        fprintf(stderr, "\nCHILD THREAD %d TERMINATED with exec_terminate\n  ROUTINE: %s\n  DIAGNOSTIC: %s\n"
×
218
         "  THREAD STOP TIME: %f\n" ,
219
         thread_id, ex.file.c_str(), ex.message.c_str(), exec_get_sim_time()) ;
220
        exit(ex.ret_code) ;
×
221
#ifdef __linux
222
    // for post gcc 4.1.2
223
    } catch (abi::__forced_unwind&) {
10✔
224
        //pthread_exit and pthread_cancel will cause an abi::__forced_unwind to be thrown. Rethrow it.
225
        throw;
5✔
226
#endif
227
    }
228

229
    pthread_exit(NULL) ;
230
    return 0 ;
231
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc