Perk Tk Memory leak - linux

I have the perl Tk subroutine below that when run repeatedly on some of the Centos 6 machines on our small private LAN get the following error:
0 0x95ac3b8 PVMG f=0008e507 {}(1)(3)
SV = PVMG(0x9471dc0) at 0x95ac3b8
REFCNT = 3
FLAGS = (PADBUSY,PADMY,GMG,SMG,RMG,ROK)
IV = 0
NV = 0
RV = 0x95c2060
PV = 0x95c2060 ""
CUR = 0
LEN = 0
MAGIC = 0x95dfa38
MG_VIRTUAL = 0x28173c
MG_TYPE = PERL_MAGIC_ext(~)
MG_FLAGS = 0x02
REFCOUNTED
MG_OBJ = 0x95c239c
SV = PV(0x95d26bc) at 0x95c239c
REFCNT = 1
FLAGS = ()
PV = 0x95dfbf0 ""
CUR = 0
LEN = 16
Tk::Error: Usage $widget->destroy(...) at ./Tk_carr_docs_check_box.pl line 89.
Tk callback for .frame1.button
Tk::__ANON__ at /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/Tk.pm line 250
Tk::Button::butUp at /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/Tk/Button.pm line 175
<ButtonRelease-1>
(command bound to event)
I have read that this is caused because destroy is called and that I should use packForget() instead. However, I have not been able to understand how to substitute packForget() for destroy. I have tried various methods such as replacing 'destroy' with 'packForget', packForget(), pack->('forget'), in a subroutine with $mw->packForget() but none has worked. Does anyone know how I can replace destroy with packForget in this case to see if it cures my memory leak problem?
To reproduce this on a linux machine copy and paste. When you execute pick "OCP Docs" at the first window dialog box. It will then pull up a second check box window. At that second window select any combination and press ok. Continue doing this a few times and the memory leak occurs. Just reproduced it on a debian machine.
#!/usr/bin/perl
#####################
sub choose_doc_type {
#####################
use strict;
use Tk;
use Tk::LabFrame;
my $mw = MainWindow->new;
# Mainwindow: sizex/y, positionx/y
$mw->geometry("210x260-0+0");
# Default value
my $doc_type = "";
my $frame = $mw->LabFrame(
-label => "Fax/Doc Type",
-labelside => 'acrosstop',
-width => 180,
-height => 200,
)->place(-x=>10,-y=>10);
# Put these values into the frame
$frame->Radiobutton(
-variable => \$doc_type,
-value => 'RC_SAVE',
-text => 'Docs for RC',
)->place( -x => 10, -y => 5 );
$frame->Radiobutton(
-variable => \$doc_type,
-value => 'OCP_SAVE',
-text => 'OCP Docs',
)->place( -x => 10, -y => 30 );
$frame->Radiobutton(
-variable => \$doc_type,
-value => 'NV_SAVE',
-text => 'New Vendor Docs.',
)->place( -x => 10, -y => 55 );
$frame->Radiobutton(
-variable => \$doc_type,
-value => 'DELETE',
-text => 'Junk. Delete it',
)->place( -x => 10, -y => 80 );
$frame->Radiobutton(
-variable => \$doc_type,
-value => 'NADA',
-text => 'Leave it.',
)->place( -x => 10, -y => 105 );
$frame->Radiobutton(
-variable => \$doc_type,
-value => 'SAVE_FAX',
-text => 'Other - Save it',
)->place( -x => 10, -y => 130 );
$frame->Radiobutton(
-variable => \$doc_type,
-value => 'AP_SAVE',
-text => 'AP Docs',
)->place( -x => 10, -y => 130 );
my $button_frame = $mw->Frame()->pack(-side => "bottom");
my $ok_button = $button_frame->Button(-text => 'OK',
-command => [$mw=>'destroy']
)->pack(-side => "left");
MainLoop;
#print $doc_type . "\n";
#chomp (my $jj = <STDIN>);
return $doc_type;
############################
} # end of sub choose doc type
############################
#####################
sub carr_docs_box {
#####################
my ($c_no) = #_;
use Tk;
use strict;
my $mw = MainWindow->new;
$mw->geometry("180x270-0-30");
$mw->title("Check Button Select");
my #check;
my $doc_string;
$check[1];
$check[2];
$check[3];
$check[4];
$check[5];
$check[6];
$check[7];
$check[8];
$check[9];
my $check_frame = $mw->Frame()->pack(-side => "top");
$check_frame->Label(-text=>"Select Included Documents.")->pack(-side => "top")->pack();
my #chk;
$chk[1] = $check_frame->Checkbutton(-text => 'BC Agrm',
-variable => \$check[1],
-onvalue => '_BCA',
-offvalue => '')->pack();
$chk[2] = $check_frame->Checkbutton(-text => 'Bond',
-variable => \$check[2],
-onvalue => '_ATH',
-offvalue => '')->pack();
$chk[3] = $check_frame->Checkbutton(-text => 'Gen Liab. Insr.',
-variable => \$check[3],
-onvalue => '_INL',
-offvalue => '')->pack();
$chk[4] = $check_frame->Checkbutton(-text => 'Auto Insr.',
-variable => \$check[4],
-onvalue => '_INC',
-offvalue => '')->pack();
$chk[5] = $check_frame->Checkbutton(-text => 'Indp. Contractor',
-variable => \$check[5],
-onvalue => '_IND',
-offvalue => '')->pack();
$chk[6] = $check_frame->Checkbutton(-text => 'Profile',
-variable => \$check[6],
-onvalue => '_PRF',
-offvalue => '')->pack();
$chk[7] = $check_frame->Checkbutton(-text => 'W9 Form',
-variable => \$check[7],
-onvalue => '_W9',
-offvalue => '')->pack();
$chk[8] = $check_frame->Checkbutton(-text => 'Rush Pay Agrm.',
-variable => \$check[8],
-onvalue => '_RP',
-offvalue => '')->pack();
$chk[9] = $check_frame->Checkbutton(-text => 'Other',
-variable => \$check[9],
-onvalue => '_OTH',
-offvalue => '')->pack();
my $button_frame = $mw->Frame()->pack(-side => "bottom");
my $ok_button = $button_frame->Button(-text => 'OK',
-command => \&check_sub)->pack(-side => "left");
# summary sub
sub check_sub {
# check to see if they selected quick Pay
if ($check[8] eq '_RP') { # user says that recvd a Rush Pay agrm
# verify rush pay agrm and set up rush pay
rush_pay_set_up($c_no);
}
$doc_string = join "", #check;
#print "Doc " . $doc_string . "\n";
#chomp (my $TT=<STDIN>);
$mw->destroy;
}
MainLoop;
return $doc_string;
#########
} # end of sub
############
my $dt; # type of documents viewed
my $quit = 'n';
my $test_cno = 1111;
while ($quit ne 'q') {
($dt) = choose_doc_type();
print "quit equals: $quit\n";
if ($dt eq 'OCP_SAVE') { # Classify vendor docs.
my $doc_string = carr_docs_box($test_cno);
print "Doc String would be: " . $doc_string . "\n";
sub { exit; }
}
print "Press (q) to quit Enter to continue any other key to quit.\n";
chomp ($quit = <STDIN>);
}

Yes I can now reproduce the behavior you described. Seems like the problem is related to the inner sub named check_sub (located inside the carr_docs_box sub):
sub check_sub {
[...]
$mw->destroy; # <-- closure over the `$mw` variable
}
Named inner subs are stored in a global namespace at compile time, see Nested subroutines and Scoping in Perl. So when they are used as a closure over lexical variables in an outer sub, that might not be the variable that you expect. In your case, the $mw in the inner sub is not referring to the $mw in the outer sub in its second invocation. To fix it, you can pass the correct $mw explicitly in the $ok_button's command. So instead of
my $ok_button = $button_frame->Button(
-text => 'OK',
-command => \&check_sub)->pack(-side => "left");
you can do:
my $ok_button = $button_frame->Button(
-text => 'OK',
-command => sub { check_sub( $mw ) })->pack(-side => "left");
Another option is to not used named inner subs in the first place, this will probably save you and future maintainers some confusion. This is what I would do.
Also note that after Perl version 5.18, you can declare lexical subs, see perldoc perlsub for more information. Then, defining check_sub as lexical (using my sub check_sub { ... } would also solve the problem with closure.

Related

How to get a pretty print for my input file

I have a file that contains data as shown in the Input file below. My program reads the config file, and writes section of this file as individual files. I read this file using python3 and pyyaml module. I get all the data I want, but when the data is written out to the output file, instead of the pretty-printed output, there are all these extra characters HOw can I get it pretty printed?
My ugly output:
"input {\n beats {\n port => 5044\n host => \"0.0.0.0\"\n tags => [\"output_beats\"\
]\n add_field => {\n \"[es][port]\" => 5044\n \"[es][type]\" => \"\
beats\" \n \"[es][subtype]\" => \"%{[#metadata][beat]}\"\n \"[#metadata][queue_prefix]\"\
\ => \"%{[#metadata][beat]}\"\n }\n }\n}\n"
Input file:
---
# Source: logstash/templates/configmap-receiver.yaml
apiVersion: v1
... removed for clarity
data:
100_beats_receiver_input_5044.conf : |
input {
beats {
port => 5044
host => "0.0.0.0"
tags => ["output_beats"]
add_field => {
"[es][port]" => 5044
"[es][type]" => "beats"
"[es][subtype]" => "%{[#metadata][beat]}"
"[#metadata][queue_prefix]" => "%{[#metadata][beat]}"
}
}
}
My code is pretty simple:
def read_and_process_yaml_file(filePath, outputDir):
"""Read file, return parsed python structure"""
print("About to read " + filePath)
with open(filePath,'r') as input_file:
yamlDocs = load_yaml(input_file)
for doc in yamlDocs:
print(yaml.dump(doc))
if (doc is not None) \
and (doc["kind"] is not None) and (doc["kind"].lower() == 'configmap') \
and ("test" not in doc["metadata"]["name"]):
print("doc.name=" + doc["metadata"]["name"])
for name, data in doc["data"].items():
print("name=" + name)
basename = name.split(".",1)
filePath = outputDir + "/" + basename[0] + ".yaml"
print(name + "|-")
#print(yaml.dump(data))
write_yaml_file(yaml.dump(data), filePath)
data is the string containing the desired output. If you do yaml.dump(data), you encode that string as a YAML scalar. Just do
write_yaml_file(data, filePath)

How to clean up files created by Exec resources?

I am trying to write a puppet class that will create a cirros image with OpenStacks Glance.
I have this puppet class. It downloads the image file and converts it to raw.
It then creates the glance image using the raw image format file.
I also want to remove the downloaded image file and the raw image file from
local disk.
Here is the manifest I tried:
class create_glance_cirros_image (
$cirrosver = '0.3.5',
$cirros_download_url = 'http://download.cirros-cloud.net',
$curl = '/usr/bin/curl',
$download_dir = '/root',
$qemu_img = '/usr/bin/qemu-img',
$qemu_img_args = 'convert -f qcow2 -O raw',
$image_name = 'cirros',
$is_public = 'no',
$container_format = 'bare',
$disk_format = 'raw',
$min_ram = '1024',
$min_disk = '1',
$properties = { 'img_key' => img_value },
$ensure = 'present',
) {
$cirros_image = "cirros-${cirrosver}-x86_64-disk.img"
$raw_cirros_image = "cirros-${cirrosver}-x86_64-disk.raw"
$image_url = "${cirros_download_url}/${cirrosver}/${cirros_image}"
$target_file = "${download_dir}/${cirros_image}"
$raw_target_file = "${download_dir}/${raw_cirros_image}"
$curl_args = "--output ${target_file}"
$download_command = "${curl} ${curl_args} ${image_url}"
$convert_command = "${qemu_img} ${qemu_img_args} ${target_file} ${raw_target_file}"
exec { $download_command:
creates => $target_file,
refreshonly => true,
}
exec { $convert_command:
creates => $raw_target_file,
refreshonly => true,
require => Exec[$download_command],
}
glance_image { $image_name:
ensure => $ensure,
name => $image_name,
is_public => $is_public,
container_format => $container_format,
disk_format => $disk_format,
source => $raw_target_file,
min_ram => $min_ram,
min_disk => $min_disk,
properties => $properties,
require => Exec[$convert_command],
}
file { $target_file:
ensure => 'absent',
}
file { $raw_target_file:
ensure => 'absent',
}
}
When I run it I get this error:
Error: Execution of '/usr/bin/openstack image create --format shell cirros --private --container-format=bare --disk-format=raw --min-disk=1 --min-ram=1024 --property img_key=img_value --file=/root/cirros-0.3.5-x86_64-disk.raw' returned 1: [Errno 2] No such file or directory: '/root/cirros-0.3.5-x86_64-disk.raw'
Error: /Stage[main]/Create_glance_cirros_image/Glance_image[cirros]/ensure: change from absent to present failed: Execution of '/usr/bin/openstack image create --format shell cirros --private --container-format=bare --disk-format=raw --min-disk=1 --min-ram=1024 --property img_key=img_value --file=/root/cirros-0.3.5-x86_64-disk.raw' returned 1: [Errno 2] No such file or directory: '/root/cirros-0.3.5-x86_64-disk.raw'
Why didn't the require cause the exec's to execute?
Update: Based on Matt's suggestions I modified my manifest to look like this:
exec { $download_command:
creates => $target_file,
unless => "/usr/bin/openstack image list --format=value | cut -d' ' -f2 | grep \"^${image_name}$\"",
notify => Exec[$convert_command],
}
exec { $convert_command:
creates => $raw_target_file,
refreshonly => true,
}
glance_image { $image_name:
ensure => present,
name => $image_name,
is_public => $is_public,
container_format => $container_format,
disk_format => $disk_format,
source => $raw_target_file,
min_ram => $min_ram,
min_disk => $min_disk,
properties => $properties,
}
exec { "/bin/rm -f ${target_file}":
subscribe => Exec[$convert_command],
refreshonly => true,
}
file { $raw_target_file:
ensure => 'absent',
require => Glance_image[$image_name],
}
Setting your exec resources to refreshonly means that they require a refresh signal to trigger and be applied. This can be done with a subscribe or a notify. Since your second exec depends upon the first, you can do this as:
exec { $download_command:
creates => $target_file,
refreshonly => true,
notify => Exec[$convert_command],
}
or:
exec { $convert_command:
creates => $raw_target_file,
refreshonly => true,
subscribe => Exec[$download_command],
}
The first one is trickier since it does not establish a relationship with anything. If you want the file download to be idempotent, I would recommend using a file resource instead.
file { $target_file:
source => $image_url,
}
This would cause both of your resources to be idempotent and apply when only when you want them to, thus achieving your goal.
You would need to modify your image file removal to be an exec though. Something like this would work:
exec { "/bin/rm -f ${target_file}":
subscribe => Exec[$convert_command]
refreshonly => true,
}
Your raw image file removal also needs to be applied after its creation and usage:
file { $raw_target_file:
ensure => 'absent',
require => Glance_image[$image_name],
}

CHECK_GEARMAN CRITICAL - function 'BulkEmail' is not registered in the server

I am using the nagios to monitor gearman and getting error "CRITICAL - function 'xxx' is not registered in the server"
Script that nagios execute to check the gearman is like
#!/usr/bin/env perl
# taken from: gearmand-0.24/libgearman-server/server.c:974
# function->function_name, function->job_total,
# function->job_running, function->worker_count);
#
# this code give following result with gearadmin --status
#
# FunctionName job_total job_running worker_count
# AdsUpdateCountersFunction 0 0 4
use strict;
use warnings;
use Nagios::Plugin;
my $VERSION="0.2.1";
my $np;
$np = Nagios::Plugin->new(usage => "Usage: %s -f|--flist <func1[:threshold1],..,funcN[:thresholdN]> [--host|-H <host>] [--port|-p <port>] [ -c|--critworkers=<threshold> ] [ -w|--warnworkers=<threshold>] [-?|--usage] [-V|--version] [-h|--help] [-v|--verbose] [-t|--timeout=<timeout>]",
version => $VERSION,
blurb => 'This plugin checks a gearman job server, expecting that every function in function-list arg is registered by at least one worker, and expecting that job_total is not too much high.',
license => "Brought to you AS IS, WITHOUT WARRANTY, under GPL. (C) Remi Paulmier <remi.paulmier\#gmail.com>",
shortname => "CHECK_GEARMAN",
);
$np->add_arg(spec => 'flist|f=s',
help => q(Check for the functions listed in STRING, separated by comma. If optional threshold is given (separated by :), check that waiting jobs for this particular function are not exceeding that value),
required => 1,
);
$np->add_arg(spec => 'host|H=s',
help => q(Check the host indicated in STRING),
required => 0,
default => 'localhost',
);
$np->add_arg(spec => 'port|p=i',
help => q(Use the TCP port indicated in INTEGER),
required => 0,
default => 4730,
);
$np->add_arg(spec => 'critworkers|c=i',
help => q(Exit with CRITICAL status if fewer than INTEGER workers have registered a particular function),
required => 0,
default => 1,
);
$np->add_arg(spec => 'warnworkers|w=i',
help => q(Exit with WARNING status if fewer than INTEGER workers have registered a particular function),
required => 0,
default => 4,
);
$np->getopts;
my $ng = $np->opts;
# manage timeout
alarm $ng->timeout;
my $runtime = {'status' => OK,
'message' => "Everything OK",
};
# host & port
my $host = $ng->get('host');
my $port = $ng->get('port');
# verbosity
my $verbose = $ng->get('verbose');# look for gearadmin, use nc if not found
my #paths = grep { -x "$_/gearadmin" } split /:/, $ENV{PATH};
my $cmd = "gearadmin --status -h $host -p $port";
if (#paths == 0) {
print STDERR "gearadmin not found, using nc\n" if ($verbose != 0);
# $cmd = "echo status | nc -w 1 $host $port";
$cmd = "echo status | nc -i 1 -w 1 $host $port";
}
foreach (`$cmd 2>/dev/null | grep -v '^\\.'`) {
chomp;
my ($fname, $job_total, $job_running, $worker_count) =
split /[[:space:]]+/;
$runtime->{'funcs'}{"$fname"} = {job_total => $job_total,
job_running => $job_running,
worker_count => $worker_count };
# print "$fname : $runtime->{'funcs'}{\"$fname\"}{'worker_count'}\n";
}
# get function list
my #flist = split /,/, $ng->get('flist');
foreach (#flist) {
my ($fname, $fthreshold);
if (/\:/) {
($fname, $fthreshold) = split /:/;
} else {
($fname, $fthreshold) = ($_, -1);
}
# print "defined for $fname: $runtime->{'funcs'}{\"$fname\"}{'worker_count'}\n";
# if (defined($runtime->{'funcs'}{"$fname"})) {
# print "$fname is defined\n";
# } else {
# print "$fname is NOT defined\n";
# }
if (!defined($runtime->{'funcs'}{"$fname"}) &&
$runtime->{'status'} <= CRITICAL) {
($runtime->{'status'}, $runtime->{'message'}) =
(CRITICAL, "function '$fname' is not registered in the server");
} else {
if ($runtime->{'funcs'}{"$fname"}{'worker_count'} <
$ng->get('critworkers') && $runtime->{'status'} <= CRITICAL) {
($runtime->{'status'}, $runtime->{'message'}) =
(CRITICAL,
"less than " .$ng->get('critworkers').
" workers were found having function '$fname' registered.");
}
if ($runtime->{'funcs'}{"$fname"}{'worker_count'} <
$ng->get('warnworkers') && $runtime->{'status'} <= WARNING) {
($runtime->{'status'}, $runtime->{'message'}) =
(WARNING,
"less than " .$ng->get('warnworkers').
" workers were found having function '$fname' registered.");
}
if ($runtime->{'funcs'}{"$fname"}{'job_total'} > $fthreshold
&& $fthreshold != -1 && $runtime->{'status'}<=WARNING) {
($runtime->{'status'}, $runtime->{'message'}) =
(WARNING,
$runtime->{'funcs'}{"$fname"}{'job_total'}.
" jobs for $fname exceeds threshold $fthreshold");
}
}
}
$np->nagios_exit($runtime->{'status'}, $runtime->{'message'});
When the script is executed simply by command line it says "everything ok"
But in nagios it shows error "CRITICAL - function 'xxx' is not registered in the server"
Thanks in advance
After spending long time on this, finally got the answer all that have to do is.
yum install nc
nc is what that was missing from the system.
With Regards,
Bankat Vikhe
Not easy to say but it could be related to your script not being executable as embedded Perl.
Try with # nagios: -epn at the beginning of the script.
#!/usr/bin/env perl
# nagios: -epn
use strict;
use warnings;
Be sure to check all the hints in the Perl Plugins section of the Nagios Plugin Development Guidelines

puppet: Syntax error at 'target'; expected '}' - parsing error

Syntax error while parsing puppet resource.
class nagios::export {
##nagios_host { $::fqdn:
address => $::ipaddress,
use => "linux-server",
check_command => 'check-host-alive!3000.0,80%!5000.0,100%!10',
hostgroups => 'all-servers',
target => "/etc/nagios/resource.d/host_${::fqdn}.cfg"
}
##nagios_service { "check_ping_${hostname}":
check_command => "check-host-alive!100.0,20%!500.0,60%",
use => "generic-service",
host_name => "$fqdn",
notification_period => "24x7",
#target => "/etc/nagios/resource.d/service_${::fqdn}.cfg"
service_description => "${hostname}_check_ping"
target => "/etc/nagios/resource.d/service_${::fqdn}.cfg"
}
}
When I run puppet apply , following error is seen..
[root#ip-10-172-161-25 manifests]# puppet apply export.pp --noop
Could not parse for environment production: Syntax error at 'target'; expected '}' at /etc/puppet/modules/nagios/manifests/export.pp:28 on node ip-10-172-161-25.us-west-1.compute.internal
class nagios::export {
##nagios_host { $::fqdn:
address => $::ipaddress,
use => "linux-server",
check_command => 'check-host-alive!3000.0,80%!5000.0,100%!10',
hostgroups => 'all-servers',
target => "/etc/nagios/resource.d/host_${::fqdn}.cfg",
}
##nagios_service { "check_ping_${hostname}":
check_command => "check-host-alive!100.0,20%!500.0,60%",
use => "generic-service",
host_name => "$fqdn",
notification_period => "24x7",
#target => "/etc/nagios/resource.d/service_${::fqdn}.cfg",
service_description => "${hostname}_check_ping",
target => "/etc/nagios/resource.d/service_${::fqdn}.cfg",
}
}
Was just a few missing commas at the end.
I generally always finish with a comma on the last line. It's not needed, but catches gotcha's that happen when you add an extra line to the end.

file array giving different result for different browser

I am uploading a file in cake php.
<?php echo $form->create("Video",array('action'=>'add','name'=>'thisform','enctype'=>'multipart/formdata','onsubmit'=>'javascript: return validate();'));
echo $form->input("file_name",array('type'=>'file','id'=>'file_name','label'=>'','div'=>''));
echo $form->end();?>
In chrome I am getting the below
Array(
[Video] => Array(
[file_name] => Array(
[name] => imp.txt
[type] => text/plain
[tmp_name] => D:\xampp\tmp\php63.tmp
[error] => 0
[size] => 1568
)
)
)
But in mozilla i am getting the below
Array(
[Video] => Array(
[file_name] =>
)
)
As I was using
'enctype'=>'multipart/formdata' ;it was not working in mozilla.
But when I write
'enctype'=>'multipart/form-data' and it works.

Resources