This discussion is archived
6 Replies Latest reply: Aug 17, 2010 3:09 AM by 807559 RSS

clause local variable question

807559 Newbie
Currently Being Moderated
Hi,

I still don't have a glue how clause local variables work. Using the simple D :

#pragma D option quiet

int this  x;


BEGIN
{
  check1 = 0;
  check2 = 0;
}

syscall::read:entry
/ execname == "in.mpathd" /
{
  this->x = check1 != 0 ? this->x : 1;
  check1 = 1;
  printf("1st clause: %d \n", this->x);
}

syscall::read:entry
/ execname == "in.mpathd" /
{
  printf("2nd clause: %d \n", this->x++);
}

syscall::write:entry
/ execname == "in.mpathd" /
{
  this->x =  check2 != 0 ? this->x : 1000;
  check2 = 1;
  printf("3nd clause: %d \n", this->x);
}
I am getting the following result:

3nd clause: 1000
1st clause: 1
2nd clause: 1
3nd clause: 2
1st clause: 2
2nd clause: 2
3nd clause: 3
1st clause: 3
2nd clause: 3
3nd clause: 4
1st clause: 4
2nd clause: 4
3nd clause: 5
1st clause: 5
2nd clause: 5
3nd clause: 6
1st clause: 6
2nd clause: 6
3nd clause: 7
1st clause: 7
2nd clause: 7
3nd clause: 8
1st clause: 8
2nd clause: 8
3nd clause: 9
1st clause: 9
2nd clause: 9
3nd clause: 10
1st clause: 10
2nd clause: 10
3nd clause: 0
1st clause: 0
2nd clause: 0
3nd clause: 1
1st clause: 1
2nd clause: 1
3nd clause: 2
1st clause: 2
2nd clause: 2
3nd clause: 0
1st clause: 0
2nd clause: 0
3nd clause: 3
1st clause: 3
2nd clause: 3
3nd clause: 1
1st clause: 1
2nd clause: 1
3nd clause: 2
1st clause: 2
2nd clause: 2
3nd clause: 3
1st clause: 3
2nd clause: 3
3nd clause: 4
1st clause: 4
2nd clause: 4
3nd clause: 5
1st clause: 5
2nd clause: 5
3nd clause: 6
1st clause: 6
2nd clause: 6
3nd clause: 7
1st clause: 7
2nd clause: 7
3nd clause: 8
1st clause: 8
2nd clause: 8
3nd clause: 9
1st clause: 9
2nd clause: 9
3nd clause: 10
1st clause: 10
2nd clause: 10
3nd clause: 11
1st clause: 11
2nd clause: 11
3nd clause: 12
1st clause: 12
2nd clause: 12
3nd clause: 0
1st clause: 0
2nd clause: 0
3nd clause: 11
1st clause: 11
2nd clause: 11
I was expecting that the value of this->x within syscall::read:entry should be incremented by 1 as the probe fires and this->x within syscall::write:entry should remain 1000. Hmm...
  • 1. Re: clause local variable question
    807559 Newbie
    Currently Being Moderated
    This sounds like object-oriented thinking applied to DTrace, which is not quite what clause-local variables promise. Consider this passage in the Solaris Dynamic Tracing Guide, pp. 67:

    Clause-local variables are only active for the lifetime of a given probe clause. After DTrace performs the actions associated with your clauses for a given probe, the storage for all clause-local variables is reclaimed and reused for the next clause. For this reason, clause-local variables are the only D variables that are not initially filled with zeroes. Note that if your program contains multiple clauses for a single probe, any clause-local variables will remain intact as the clauses are executed...

    The sanity of a clause-local variable used in multiple clauses for the same probe definition is guaranteed; separate, sanitized storage space for each probe definition in the program is not. So when syscall::write:entry accesses this->x, it finds what syscall::read:entry left behind.

    Just use different variables for different probe definitions. It is less confusing in any event:
    #!/usr/sbin/dtrace -s
    
    #pragma D option quiet
    
    BEGIN
    {
            printf("BEGIN");
            this->y = 99;
    }
    
    syscall::read:entry
    / !this->x /
    {
            this->x = 0;
            printf("Clause %d: %d\n", epid, this->x);
    }
    
    syscall::read:entry
    {
            printf("Clause %d: %d\n", epid, this->x++);
    }
    
    syscall::read:entry
    / this->x == 20 /
    {
            printf("Clause %d: %d\n", epid, this->x);
            exit(0);
    }
    
    syscall::write:entry
    {
            printf("Clause %d: %d\n", epid, this->y++);
    }
  • 2. Re: clause local variable question
    807559 Newbie
    Currently Being Moderated
    Hello Michael,

    thank you for the explanation. The output of your D brings some new questions:
    BEGINClause 2: 0
    Clause 3: 0
    Clause 3: 1
    Clause 5: 0      -> should be 99 ?
    Clause 3: 2
    Clause 5: 0
    Clause 2: 0      -> should not be reentered again?
    Clause 3: 0
    Clause 3: 1
    Clause 3: 2
    Clause 3: 3
    Clause 5: 99
    Clause 5: 100
    Clause 5: 101
    Clause 5: 102
    Clause 5: 103
    Clause 5: 104
    Clause 5: 105
    Clause 5: 106
    Clause 5: 107
    Clause 5: 108
    Clause 5: 109
    Clause 2: 0
    Clause 3: 0
    Clause 3: 1
    Clause 5: 0
    Clause 3: 2
    Clause 5: 1
    Clause 3: 3
    Clause 3: 4
    Clause 3: 5
    Clause 3: 6
    Clause 3: 7
    Clause 5: 1
    Clause 3: 8
    Clause 3: 9
    Clause 5: 2
    Clause 3: 10
    Clause 3: 11
    Clause 5: 3
    Clause 3: 12
    Clause 3: 13
    Clause 5: 4
    Clause 3: 14
    Clause 3: 15
    Clause 5: 5
    Clause 5: 110
    Clause 5: 111
    Clause 5: 112
    Clause 5: 113
    Clause 5: 114
    Clause 5: 115
    Clause 5: 116
    Clause 5: 117
    Clause 5: 118
    Clause 5: 119
    Clause 5: 120
    Clause 5: 121
    Clause 5: 122
    Clause 5: 123
    Clause 5: 124
    Clause 5: 125
    Clause 5: 126
    Clause 2: 0
    Clause 3: 0
    Clause 5: 127
    Clause 3: 1
    Clause 5: 128
    Clause 3: 2
    Clause 5: 129
    Clause 3: 3
    Clause 5: 2   -> should be 130?
    Clause 3: 4
    Clause 5: 3
    Clause 3: 5
    Clause 5: 4
    Clause 5: 5
    Clause 5: 6
    Clause 3: 6
    Clause 3: 7
    Clause 3: 8
    Clause 5: 7
    Clause 3: 9
    Clause 3: 10
    Clause 3: 11
    Clause 5: 8
    Clause 3: 12
    Clause 3: 13
    Clause 3: 14
    Clause 5: 9
    Clause 3: 15
    Clause 3: 16
    Clause 3: 17
    Clause 5: 10
    Clause 3: 18
    Clause 3: 19
    Clause 4: 20     -> should exit here?
    Clause 5: 1       -> 1 again?
    Clause 3: 4
    Clause 3: 5
    Clause 3: 6
    Clause 5: 2
    Clause 3: 7
    Clause 3: 8
    Clause 3: 9
    Clause 5: 3
    Clause 3: 10
    Clause 3: 11
    Clause 3: 12
    I'm wondering that the initial value of probe 5 is 0, not 99.
    Should not have the action of Clause 2 executed just once, because of the predicate / !this->x / ? But it appears several times.
    After Clause 4: 20 the D should exit. Why are there still probes firing and why the value of this->x has become 4 ?
    Should not clause 5 increment this->y by 1 if it's fired? Why does this->y get values < 99 ?

    Edited by: go_insane on Aug 11, 2010 3:18 AM
  • 3. Re: clause local variable question
    807559 Newbie
    Currently Being Moderated
    Oy.

    I changed the assignment in clause 2 to this->x = 1, rather than zero. My tests did not re-enter clause 2 after that.

    I did not get clause 5 to output 99. I have a guess why, but I don't want to offer it until you make the change above. I'd be curious to see if clause 5 reporting zero goes away, which I think it will.

    I also did not see clause 5 report incorrectly after this change.

    If all that works the same for you, then let's look at why your clause 4 did not exit when it should have.
  • 4. Re: clause local variable question
    807559 Newbie
    Currently Being Moderated
    Hello Michael,

    i've changed this->x to 1 in clause 2.
    But the result is curious again:

    BEGINClause 5: 0
    Clause 5: 1
    Clause 5: 99
    Clause 5: 100
    Clause 2: 1
    Clause 3: 1
    Clause 5: 2
    Clause 5: 0
    Clause 2: 1
    Clause 3: 1
    Clause 5: 1
    Clause 3: 2
    Clause 5: 101
    Clause 5: 102
    Clause 5: 103
    Clause 5: 104
    Clause 5: 105
    Clause 5: 106
    Clause 5: 107
    Clause 5: 108
    Clause 5: 109
    Clause 5: 110
    Clause 5: 111
    Clause 5: 112
    Clause 3: 2
    Clause 3: 3
    Clause 5: 3
    Clause 3: 4
    Clause 5: 4
    Clause 5: 5
    Clause 3: 5
    Clause 3: 6
    Clause 5: 6
    Clause 3: 7
    Clause 3: 8
    Clause 3: 9
    Clause 3: 10
    Clause 5: 7
    Clause 5: 8
    Clause 5: 9
    Clause 5: 10
    Clause 5: 2
    Clause 3: 3
    Clause 3: 4
    Clause 5: 3
    Clause 3: 5
    Clause 5: 113
    Clause 5: 114
    Clause 5: 115
    Clause 5: 116
    Clause 5: 117
    Clause 5: 118
    Clause 5: 119
    Clause 5: 120
    Clause 5: 121
    Clause 5: 122
    Clause 5: 123
    Clause 5: 124
    Clause 2: 1
    Clause 3: 1
    Clause 3: 2
    Clause 5: 125
    Clause 3: 3
    Clause 3: 4
    Clause 3: 5
    Clause 3: 6
    Clause 3: 7
    Clause 5: 126
    Clause 5: 127
    Clause 5: 128
    Clause 5: 129
    Clause 5: 130
    Clause 5: 131
    Clause 5: 132
    Clause 5: 133
    Clause 5: 134
    Clause 5: 135
    Clause 5: 136
    Clause 5: 137
    Clause 5: 138
    Clause 5: 139
    Clause 5: 140
    Clause 5: 141
    Clause 5: 142
    Clause 5: 143
    Clause 5: 144
    Clause 5: 145
    Clause 5: 146
    Clause 5: 147
    Clause 5: 148
    Clause 5: 149
    Clause 5: 0
    Clause 3: 11
    Clause 3: 12
    Clause 5: 11
    Clause 3: 13
    Clause 5: 12
    Clause 3: 14
    Clause 5: 13
    Clause 3: 15
    Clause 5: 14
    Clause 3: 16
    Clause 5: 15
    Clause 3: 17
    Clause 5: 16
    Clause 3: 18
    Clause 5: 17
    Clause 3: 19
    Clause 4: 20
    Clause 5: 150
    Clause 5: 151
    Clause 5: 152
    Clause 5: 153
    Clause 5: 154
    Clause 5: 155
    Clause 5: 156
    Clause 5: 157
    Clause 5: 158
    Clause 5: 159
    Clause 5: 160
    Clause 5: 161
    Clause 5: 162
    Clause 5: 163
    Clause 5: 164
    Clause 5: 165
    Clause 5: 166
    Clause 5: 167
    Clause 5: 168
    Clause 5: 169
    Clause 5: 170
    Edited by: go_insane on Aug 16, 2010 6:10 AM
  • 5. Re: clause local variable question
    807559 Newbie
    Currently Being Moderated
    Post the script you are now working with?
  • 6. Re: clause local variable question
    807559 Newbie
    Currently Being Moderated
    #!/usr/sbin/dtrace -s
    
    #pragma D option quiet
    
    BEGIN
    {
            printf("BEGIN");
            this->y = 99;
    }
    
    syscall::read:entry
    / !this->x /
    {
            this->x = 1;
            printf("Clause %d: %d\n", epid, this->x);
    }
    
    syscall::read:entry
    {
            printf("Clause %d: %d\n", epid, this->x++);
    }
    
    syscall::read:entry
    / this->x == 20 /
    {
            printf("Clause %d: %d\n", epid, this->x);
            exit(0);
    }
    
    syscall::write:entry
    {
            printf("Clause %d: %d\n", epid, this->y++);
    }