Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
uG
Apr 23, 2003

by Ralp

leedo posted:

I don't think that is possible. You would probably have to do an svn checkout and install that way. I don't really see the point in doing that, I can't imagine much is changing on the userspace end of things.

edit: speaking of which, there was a good interview with mst about Catamoose today
http://jjnapiorkowski.vox.com/library/post/catamoose-part-two-mst-speaks.html
I didn't even think of putting methods in my DBIC Schemas :haw:

Adbot
ADBOT LOVES YOU

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
You can subclass ResultSets too. This allows me to call $db->rs('domains.domain_names')->search_by_domain('foo.com') and still use indexes/joins properly.

It's nice to encapsulate larger, reusable queries into one callable name, instead of copy and pasting the same SQL query in 13 different files :(

code:
package DBIx::domains::ResultSet::domain_names;
use base 'DBIx::Class::ResultSet';

sub search_by_domain {
  my ( $self, $domain ) = @_;

  my ($domain_name, @extension) = split /[.]/ => $domain;
  my $extension = "." . join('.' => @extension);

  my $constraint = {
    domainname  => $domain_name,
    extension   => $extension,
  };

  my $options = {
    join => [qw/extension/],
  };

  return $self->search( $constraint, $options );
}

Mario Incandenza fucked around with this message at 11:28 on Sep 9, 2008

uG
Apr 23, 2003

by Ralp
Well, I couldn't figure out how to get any of this crap to work in my Catalyst's dbic schemas haha

:saddowns:

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Are you putting them inside your DBIC Schema, (e.g. MyDB/Schema/Table.pm), or MyApp/Model/MyDB/Table.pm? The model is just a wrapper around the schema, you'll need to place your custom methods in the schema if you want to reuse them properly outside of Catalyst.

uG
Apr 23, 2003

by Ralp

SpeedFrog posted:

Are you putting them inside your DBIC Schema, (e.g. MyDB/Schema/Table.pm), or MyApp/Model/MyDB/Table.pm? The model is just a wrapper around the schema, you'll need to place your custom methods in the schema if you want to reuse them properly outside of Catalyst.
I originally had it in MyApp/DB/Schema/Table.pm, but when I tried to override create the code would never make it to the overridden method (but still called the original method). I move the method out of the Schema into MyApp/DB/ResultSet/Table.pm and used __PACKAGE__->resultset_class('Game::DB::ResultSet::Table'); in the Schema to point to it. Now it works.

Could I use __PACKAGE__->resultset_class('Game::DB::Schema::Table'); inside Game::DB::Schema::Table itself? I'd like to keep everything inside the schema files if possible :(

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Yup, that works just fine, in fact I believe that's the recommended place, as it sits nicely alongside your relationship definitions (you mean resultset_class('Game::DB::ResultSet::Table'), yeah?).

Also, I know it's in the docs, but it's useful enough to bear repeating... if you ever need a plain hashref, you can do this (though keep in mind the keys still will be lowercased):

code:
my $rs = MyDB::Schema::Database->resultset('Table');
my $inflator = 'DBIx::ResultClass::HashRefInflator';

eval "require $inflator";
$rs->result_class($inflator);

while (my $hashref = $rs->next) {
}

leedo
Nov 28, 2000

SpeedFrog posted:

Yup, that works just fine, in fact I believe that's the recommended place, as it sits nicely alongside your relationship definitions (you mean resultset_class('Game::DB::ResultSet::Table'), yeah?).

Also, I know it's in the docs, but it's useful enough to bear repeating... if you ever need a plain hashref, you can do this (though keep in mind the keys still will be lowercased):

code:
my $rs = MyDB::Schema::Database->resultset('Table');
my $inflator = 'DBIx::ResultClass::HashRefInflator';

eval "require $inflator";
$rs->result_class($inflator);

while (my $hashref = $rs->next) {
}
Hmm, never knew about the built in conversion to hashref. I always just wrote my own methods in the Schema. Does HashRefInflator follow foreign keys and hashref-ize the referenced objects?

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?
Inflation happens at the very end of the process, so as long as you define your join conditions by chaining calls to the resultset (as opposed to calling relations like $row->relation), your choice of inflator shouldn't impact the data you get back - just the form you receive it in.

The HashRefInflator doesn't do much more than pass through a hashref after fiddling with its values a little - ordinarily it will be blessed into DBIx::Class::Row and packed inside an object's private _column_data attribute. The class is really small, just two subs.

Mario Incandenza fucked around with this message at 10:50 on Sep 11, 2008

Puck42
Oct 7, 2005

I've been having this issue for a few weeks now and it's driving me up a wall.


I'm writing a web app using Mason and I have a custom module that contains a lot of common functions.

For some reason now, when ever I add any new function or edit an existing one mod_perl decides that the function doesn't exist and tells me that the subroutine is undefined when I know it is. Once I remove the added lines the function works fine once again.

Anyone ever have a similar issue?

Notorious b.s.d.
Jan 25, 2003

by Reene

Puck42 posted:

I've been having this issue for a few weeks now and it's driving me up a wall.


I'm writing a web app using Mason and I have a custom module that contains a lot of common functions.

For some reason now, when ever I add any new function or edit an existing one mod_perl decides that the function doesn't exist and tells me that the subroutine is undefined when I know it is. Once I remove the added lines the function works fine once again.

Anyone ever have a similar issue?

Tried turning off code caching ?

Puck42
Oct 7, 2005

Empty Threats posted:

Tried turning off code caching ?

I have, same thing happens.

uG
Apr 23, 2003

by Ralp
Ok I could use a little help regarding dbix::class and relationships. Right now I have it setup so a nation can have any number of resource_ids (which is joined on Resources, so I can add more resources later with a DB update instead of changing code). I believe I mentioned it earlier, but its a clone of the Role's tutorial from the Catalyst Manual (if that makes it any easier to understand?).

So I can call $resultset->nation->resources to get each resource object a nation has linked to it (foreach $a $resultset->nation->resources { print "resource name: $a->name resource id: $a->id"; })

(at this point i'm still probably not very clear, but I didnt even know what a database relationship was until recently so try and bear with me)

What I want to do at this point is add another relationship. Each nation can have many Trades. The trade table/schema would simply be 2 columns, id1 and id2. This is where I get really lost, because I dont know how to set a relationship with id1 OR id2. The only solution I can think of is to set a seperate relationship for id1 and id2 (2 seperate belongs_to). Then again maybe my idea is flawed to begin with, as ultimately I just want to get the Resources of all the nations that share a trade with x-nation.

A clearcut example would be nice, but even some direction in where to go as far as this whole relationship thing is concerned would be wonderful :)
code:
package Game::DB::Schema::Nation;

use base qw/DBIx::Class/;

__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('nation_info');
__PACKAGE__->add_columns(qw/id name owner/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->belongs_to(user => 'Game::DB::Schema::User', 'owner');
__PACKAGE__->has_many(map_nation_resource => 'Game::DB::Schema::NationResource', 'nation_id');
__PACKAGE__->many_to_many(resources => 'map_nation_resource', 'resource');

__PACKAGE__->resultset_class('Game::DB::ResultSet::Nation');
=head2 Example Table
id          name          owner
14          somename1     some_number(relates to user)
11          somename2     some_number(relates to user)
=cut
code:
package Game::DB::Schema::NationResource;

use base qw/DBIx::Class/;

# Load required DBIC stuff
__PACKAGE__->load_components(qw/PK::Auto Core/);
# Set the table name
__PACKAGE__->table('nation_resources');
# Set columns in table
__PACKAGE__->add_columns(qw/nation_id resource_id/);
# Set the primary key for the table
__PACKAGE__->set_primary_key(qw/nation_id resource_id/);
__PACKAGE__->belongs_to(nation => 'Game::DB::Schema::Nation', 'nation_id');
__PACKAGE__->belongs_to(resource => 'Game::DB::Schema::Resource', 'resource_id');
=head2 Example Table
nation_id          resource_id
14                 lumber
14                 water
14                 fish
11                 iron
11                 water
=cut
code:
package Game::DB::Schema::Resource;

use base qw/DBIx::Class/;

# Load required DBIC stuff
__PACKAGE__->load_components(qw/PK::Auto Core/);
# Set the table name
__PACKAGE__->table('resources');
# Set columns in table
__PACKAGE__->add_columns(qw/id resource/);
# Set the primary key for the table
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(map_nation_resource => 'Game::DB::Schema::NationResource', 'resource_id');

__PACKAGE__->resultset_class('Game::DB::ResultSet::Resource');

=head2 Example Table
id          resource
1           lumber
2           water
4           fish
10          iron
=cut

Mario Incandenza
Aug 24, 2000

Tell me, small fry, have you ever heard of the golden Triumph Forks?

Puck42 posted:

I have, same thing happens.
It's related to how Apache::Registry caches its code, see here for more info. Asterisk's res_perl works similarly to mod_perl and exhibits the same behaviour. I'd make absolutely sure your modules are cleanly designed and contain no syntax errors or anything that may prevent correct parsing. If you delete a subroutine from a package's symbol table and then fail to replace it before calling it you should see similar errors:
code:
perl> sub foo { my $x = 2 * rand(1) }
perl> $hash = \%main::
perl> $hash->{foo}       
-> *main::foo;
perl> delete $hash->{foo}
-> *main::foo;
perl> foo()
-x> Undefined subroutine &main::foo called at (eval 94) line 1.                                                                                                                                                                                              

uG posted:

Then again maybe my idea is flawed to begin with, as ultimately I just want to get the Resources of all the nations that share a trade with x-nation.
Since you can't use a many-to-many relationship to perform a search, you just need to make a "left" and "right" column and join across them with something like this (untested):
code:
package Game::DB::Schema::Nations;

__PACKAGE__->belongs_to(
  trade_links => 'Game::DB::Schema::TradeLinks', [
   'foreign.left' => 'self.id',
   'foreign.right' => 'self.id',
  ],
);

package Game::DB::Schema::trade_links;

__PACKAGE__->belongs_to(
  nation => 'Game::DB::Schema::Nations', [
   'foreign.id' => 'self.left',
   'foreign.id' => 'self.right',
  ],
);

package main;
my $resource_rs = $nation->trade_links->search_related('nation')->search_related('resources');
And if you wanted to place a restriction at any point along the chain, just add a constraint like so:
code:
->search_related(resources => {
  price => \\'< 100',
  -or => [
    resource => 'corn',
    resource => 'bitches',
  ]
});

Mario Incandenza fucked around with this message at 17:33 on Sep 12, 2008

uG
Apr 23, 2003

by Ralp

SpeedFrog posted:

Since you can't use a many-to-many relationship to perform a search, you just need to make a "left" and "right" column and join across them with something like this (untested):
code:
package Game::DB::Schema::Nations;

__PACKAGE__->belongs_to(
  trade_links => 'Game::DB::Schema::Trades', {
   'foreign.nid1' => 'self.id',
   'foreign.nid2' => 'self.id',
  },
);

package Game::DB::Schema::Trades;

__PACKAGE__->belongs_to(
  nation => 'Game::DB::Schema::Nations', {
   'foreign.id' => 'self.nid1',
   'foreign.id' => 'self.nid2',
  },
);

package main;
my $resource_rs = $nation->trade_links->search_related('nation')->search_related('resources');
After modifying it a tiny bit to fit my catalyst app, i'm getting the following error:

code:
Can't locate object method "nation" via package "DBIx::Class::ResultSet
I posted your example (modified) to perlmonks, and it looks like it might be because belongs_to may not be able to have multiple owners? http://www.perlmonks.org/?node_id=711057

uG fucked around with this message at 19:16 on Sep 13, 2008

Fenderbender
Oct 10, 2003

You have the right to remain silent.
I don't know if this would be an ok place for this or anything, but my company is looking for web and application developers specializing in Perl. If you're interested, send me a PM and I'll give you some contact information.

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Randomly curious, what city/metropolitan area are you located in?

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

Fenderbender posted:

I don't know if this would be an ok place for this or anything, but my company is looking for web and application developers specializing in Perl. If you're interested, send me a PM and I'll give you some contact information.
Could you please activate the ability for other members here to email you? I don't have PM ability, but if you can accept remote workers i'd be very interested. Or, if you don't want to do that, you could give my ICQ/AIM or Yahoo ids in my profile a poke.

I figure 3+ years on a life system should be decent experience for what you want. :)

Mithaldu fucked around with this message at 14:59 on Sep 16, 2008

Fenderbender
Oct 10, 2003

You have the right to remain silent.

Triple Tech posted:

Randomly curious, what city/metropolitan area are you located in?

It's in Nashville, TN

Mithaldu posted:

Could you please activate the ability for other members here to email you? I don't have PM ability, but if you can accept remote workers i'd be very interested. Or, if you don't want to do that, you could give my ICQ/AIM or Yahoo ids in my profile a poke.

I figure 3+ years on a life system should be decent experience for what you want. :)

Done. I'll also drop you an IM once I get to work.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
Thanks and sent. :)

mofolotopo
May 10, 2004

TICK STAMPEDE!!!!
Any Perl/Tk goons around? I'm fairly new at it, and I've hit a bit of a snag. I want my application to launch a new window, be able to manipulate widgets in that window, and then return variables to the main application. I'm clearly doing something very stupid in the process, because my attempts to manipulate the properties of widgets in the child window always results in "Tk::Error: Can't call method "Contents" on an undefined value at blah blah blah". Clearly it doesn't know where to find the widget I'm trying to manipulate, which says to me that I'm not referring to it properly. This is the first time I've tried to do this exact thing, and I can't find anything in my Perl books or via Google that's helpful. I'm not primarily a programmer, though, so it's possible that I've looked right at the answer and just not understood it.

Here are the relevant bits of code:

code:
sub toolsBatchProject{
    my $batchprojectWindow =  $mw->Toplevel;
    $batchprojectWindow->geometry("500x500");
    $batchprojectWindow->title("Batch Projection");
    
    my $batchproject_list_label = $batchprojectWindow -> Label(-text => "Lambda files:  ") -> grid(-row=>1, -column=>1, -pady=>5);
    my $batchproject_list_addbutton = $batchprojectWindow -> Button(-text=>"Add files",-width=>20, -command=>\&batchprojectAddFiles) 
               -> grid(-row=>2, -column=>1, -padx=>5);
    my $batchproject_list_clear = $batchprojectWindow -> Button(-text=>"Clear file list", -width=>20, 
               -command=>\&batchprojectClearFiles, -foreground=>'red') -> grid(-row=>3, -column=>1, -padx=>5);
    my $batchproject_files_frame = $batchprojectWindow -> Frame();
    my $batchproject_files_list = $batchproject_files_frame -> Text(-width=>40, -height=>5);
    my $batchproject_files_scrollbar = $batchproject_files_frame -> Scrollbar(-orient=>'v',-command=>[yview => $batchproject_files_list]);
    $batchproject_files_list -> configure(-yscrollcommand=>['set', $batchproject_files_scrollbar]);
    $batchproject_files_list -> grid(-row=>1, -column=>1);
    $batchproject_files_frame -> grid(-row=>1, -column=>2, -rowspan=>3, -pady=>10);
    $batchproject_files_scrollbar -> grid(-row=>1, -column=>2, -sticky=>"ns");
}

sub batchprojectAddFiles {
    my @thesefiles = $mw->getOpenFile(-multiple=>'set');
    for(@thesefiles){push (@batchproject_files, $_);}
    batchprojectUpdateFiles();
}

sub batchprojectUpdateFiles {
    $batchproject_files_list->Contents("");
    my @shortnames;
    for (@batchproject_files) {
        my @thisname = split(/\//, $_);
        push (@shortnames, $thisname[-1]);
    }
    for (@shortnames){
        $batchproject_files_list-> insert('end',"$_\n");
    }
    my $arraysize = @shortnames;
}
The subroutine toolsBatchProject is called from the main window.

The error happens any time I try to manipulate $batchproject_files_list, and indicates to me that it's just out of scope. My guess is that there's some way to refer to widgets by window, but I seriously can't find it and I really have looked. The code works fine if I just put it into the main window instead. Like I say, this is the first time I've tried to do something like this - it's almost certainly some very :downs: thing.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

mofolotopo posted:

The error happens any time I try to manipulate $batchproject_files_list, and indicates to me that it's just out of scope.

It's quite possible that you have problems that have nothing to do with scope, but you also are definitely having scope problems, so let's fix those first.

First off, the basics. Scoping rules are what determine which instance of a variable you're talking about when you mention that variable. The standard rule in most programming languages, including perl, is called lexical scoping: if a variable reference occurs inside a block that declares that variable, use the local instance of that variable; if it's declared in the next-inner-most enclosing block, use that instance; and so on until you're not inside any more blocks, which is called global scope. In perl, you declare a lexically-scoped variable by saying something like "my $x" or "my @y" somewhere in a block.

So, when batchprojectUpdateFiles uses a variable called $batchproject_files_list, that variable must exist either locally (which it hasn't been) or globally (which works without a declaration if you don't ask perl to complain about such uses). You're clearly trying to use the same variable from toolsBatchProject, but that variable has been scoped locally to that function, so you can't get at it from batchprojectUpdateFiles.

You've got a lot of options here; here's two of them. First, you could just remove the "my" from the variable in toolsBatchProject, making the variable global, so the access in batchprojectUpdateFiles will be able to find the same variable. Alternatively, you could pass the current value in as a parameter.

mofolotopo
May 10, 2004

TICK STAMPEDE!!!!

rjmccall posted:

It's quite possible that you have problems that have nothing to do with scope, but you also are definitely having scope problems, so let's fix those first.

First off, the basics. Scoping rules are what determine which instance of a variable you're talking about when you mention that variable. The standard rule in most programming languages, including perl, is called lexical scoping: if a variable reference occurs inside a block that declares that variable, use the local instance of that variable; if it's declared in the next-inner-most enclosing block, use that instance; and so on until you're not inside any more blocks, which is called global scope. In perl, you declare a lexically-scoped variable by saying something like "my $x" or "my @y" somewhere in a block.

So, when batchprojectUpdateFiles uses a variable called $batchproject_files_list, that variable must exist either locally (which it hasn't been) or globally (which works without a declaration if you don't ask perl to complain about such uses). You're clearly trying to use the same variable from toolsBatchProject, but that variable has been scoped locally to that function, so you can't get at it from batchprojectUpdateFiles.

You've got a lot of options here; here's two of them. First, you could just remove the "my" from the variable in toolsBatchProject, making the variable global, so the access in batchprojectUpdateFiles will be able to find the same variable. Alternatively, you could pass the current value in as a parameter.

Welp, it was that drat simple. For some reason I thought that a function (B) that was called from within another function (A) would be able to see the variables that were scoped to A. Clearly not the case. Thanks a bunch!

mofolotopo fucked around with this message at 06:56 on Sep 17, 2008

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!
That sort of thing is called dynamic scope. It was popular before (the much saner) lexical scope was invented. Perl supports it with the local operator.

tef
May 30, 2004

-> some l-system crap ->

Sartak posted:

That sort of thing is called dynamic scope. It was popular before (the much saner) lexical scope was invented. Perl supports it with the local operator.

It was popular with interpreted languages as it simple to implement.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

tef posted:

It was popular with interpreted languages as it simple to implement.

It's actually quite nice for small, rapidly-developed programs with no real efficiency needs. Even purely lexically-scoped languages tend to have some similar mechanism, be it implicit parameters, thread-local memory, or (if all else fails) true global variables.

s139252
Jan 1, 1970
test

mofolotopo posted:

Welp, it was that drat simple. For some reason I thought that a function (B) that was called from within another function (A) would be able to see the variables that were scoped to A. Clearly not the case. Thanks a bunch!

A subroutine definition can refer to variables that exist in the surrounding scope.

code:
package main;
use strict;

our $B;  # ie, $main::B

FOO: {
  my $a = 5;          # lexical to FOO (ie, NOT $main::a)
  $B = sub { ++$a };
  sub C { ++$a }
}

# lexical $a no longer visible

print ::C(), "\n";    # 6
print &{$B}(), "\n";  # 7

Stabby McDamage
Dec 11, 2005

Doctor Rope
On *nix, how can I determine which mountpoint owns a particular file?

If I can't find a programmatic way, I'll have to parse `mount`, which seems ugly.

There Will Be Penalty
May 18, 2002

Makes a great pet!

satest4 posted:

A subroutine definition can refer to variables that exist in the surrounding scope.

That sort of thing is called a closure. :eng101:

Pooball
Sep 21, 2005
Warm and squishy.

Stabby McDamage posted:

On *nix, how can I determine which mountpoint owns a particular file?

If I can't find a programmatic way, I'll have to parse `mount`, which seems ugly.

CPAN? :)

Stabby McDamage
Dec 11, 2005

Doctor Rope

Pooball posted:

CPAN? :)

Thanks. I searched CPAN for "mountpoint", "filesys", etc., but I didn't find that. It's perfect.

EDIT: Wait, it doesn't have a way to look up a mountpoint from a file. I ended up using the output of 'df', since you can say "df /any/file" and it will just report the mount that provides that file. I'd still prefer a pure Perl method, if one exists.

Stabby McDamage fucked around with this message at 18:10 on Sep 22, 2008

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Stabby McDamage posted:

I'd still prefer a pure Perl method, if one exists.

Here's some quick and dirty code to walk up an absolute path until we find a directory that's part of a different filesystem.

code:
#!/usr/bin/perl

use strict;
use warnings;

# Must be an absolute path.
my $file = shift;

# Get the device number of the filesystem for that path.
my ($dev) = stat $file;

# Candidate mountpoint is just that path.
my $mtpoint = $file;

while ( ) {

	# Back up a directory.
	my $newmtpoint = $mtpoint;
	$newmtpoint =~ s/\/[^\/]*$//;

	# Special case for root directory.
	if ( $newmtpoint eq "" ) {
		$mtpoint = "/";
		last;
	};

	# Check filesystem for new directory, bail if it differs.
	my ($mtdev) = stat $newmtpoint;
	last unless ( $mtdev == $dev );

	# New candidate mountpoint.
	$mtpoint = $newmtpoint;

};

# This was the highest directory we found with the same filesystem.
print "$mtpoint\n";

Paradox
May 19, 2003
I am writing a perl module that needs to do some cleanup after it has received a signal, particularly sigterm. My first thought was to just install the signal handler as part of the module, but that is probably not a good idea because it can overwrite/be overwritten by a conflicting signal handler in the caller.

Alternatively, I could just leave it up to the user to install the signal handler. This is probably an acceptable solution but it seems messy and possibly unnecessary; there should be an easier way to do it. This cleanup is an implementation detail and should be hidden from the user if at all possible.

Any advice?

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!

Paradox posted:

This cleanup is an implementation detail and should be hidden from the user if at all possible.

Perhaps you want an END block.

code:
END { unlink @temp_files }
Perl will do whatever it can to ensure that each END block is run at program termination (though some abnormal termination modes can still prevent these from running).

Also, if you're doing OO, then the method called DESTROY will be called just before an object's memory is freed.

If you really need to respond to a signal then I guess just install the signal handler.

Stabby McDamage
Dec 11, 2005

Doctor Rope

ShoulderDaemon posted:

Here's some quick and dirty code to walk up an absolute path until we find a directory that's part of a different filesystem.


That's a cool idea. I might use that.

Erasmus Darwin
Mar 6, 2001

Sartak posted:

Perhaps you want an END block.

I ran a quick test, and it looks like that doesn't work for SIGTERM:

code:
$ perl -e 'END { print "Dying!\n"; } kill("TERM", $$); sleep(120);'
Terminated
$
So he'd still need to worry about catching the signal somehow. For a general purpose module, I suspect that any solution will be slightly messy and have some suboptimal side-effects.

Stabby McDamage
Dec 11, 2005

Doctor Rope

Erasmus Darwin posted:

I ran a quick test, and it looks like that doesn't work for SIGTERM:

code:
$ perl -e 'END { print "Dying!\n"; } kill("TERM", $$); sleep(120);'
Terminated
$
So he'd still need to worry about catching the signal somehow. For a general purpose module, I suspect that any solution will be slightly messy and have some suboptimal side-effects.

You can save the original handler coderef, then call it from your handler, thus preserving whatever the user had set up:
code:
#!/usr/bin/perl

###### user code: ######
use strict;
$SIG{INT} = sub { print "original handler\n"; };

####### your module: #######

my $oldhandler = $SIG{INT};
$SIG{INT} = sub { $oldhandler->(@_); print "new handler\n"; };

####### user workload: #######
sleep 5;
$ perl x.pl
<Ctrl-C>
original handler
new handler

Triple Tech
Jul 28, 2006

So what, are you quitting to join Homo Explosion?
Are there any popular modules that depend on signal handlers? I mean, if it's your own private ecosystem, what's the harm in just straight up assigning a handler? Like you're probably the only one who's going to do it, right? :)

But yes awesome solution. Although is there some sort of FILO/FIFO argument to be had here? SIGINT is ENDish?

npe
Oct 15, 2004
I know DBI (or at least DBD::Oracle) clobbers some signal handlers, although I'm not sure what it's doing with them.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Stabby McDamage posted:

You can save the original handler coderef, then call it from your handler, thus preserving whatever the user had set up:

But that only works if he can ensure his handler is setup after the user's handler - he's in a module, so his code will be run first, and in any case the user may want to change the handler during runtime.

For a transparent solution, I'd say the module should fork a subprocess and arrange for the signals it cares about to be delivered to that process instead, then use a more transparent form of IPC like a pipe or socket to communicate that information back to the main process. Failing that, I'd just document the signal handler as part of the API, install it when you load the module, and export the function used as a handler so that if the user wants to use that signal for their own purposes, they can call the module's handler after doing whatever they wanted to do.

Adbot
ADBOT LOVES YOU

s139252
Jan 1, 1970
test

Erasmus Darwin posted:

I ran a quick test, and it looks like that doesn't work for SIGTERM:

code:
$ perl -e 'END { print "Dying!\n"; } kill("TERM", $$); sleep(120);'
Terminated
$
So he'd still need to worry about catching the signal somehow. For a general purpose module, I suspect that any solution will be slightly messy and have some suboptimal side-effects.

Try this:

code:
$ echo 'END { warn "Dying!\n" } kill("TERM", -$$)' |perl

  • Locked thread