Your race condition is: one side of fork gets to the (buffered) read before the other side gets to its seek().
I find it easier to see what is going on by using non buffered reads (sysread).
Half-offsetting (timewise) the two forks leads to consistent results.
Removing the (unnecessary) seeks()'s should also lead to consistent output size (although it could be from either
the parent or child).
$| = 1;
my $pos = tell DATA;
my $pid = fork();
my $x= IO::Handle->new();
$pid and select undef, undef, undef, 0.05;
seek $x, $pos, 0;
while( sysread $x, $_, 1 )
print $pid ? uc : lc;
select undef, undef, undef, 0.1;
1 while wait > 0;
Note the extra 'a' as a result of the seek().