Hey Joey,
I think we need a different interface to the debconf db for postinsts to
use.
Here's one suggestion:
/usr/lib/debconf/bin/db_get:
#!/usr/bin/perl -w
use strict;
use lib ".";
use Debian::DebConf::ConfigDb;
use Debian::DebConf::AutoSelect;
use Debian::DebConf::Log ':all';
# Load up previous state information.
Debian::DebConf::ConfigDb::loaddb(Debian::DebConf::Config::dbdir());
my $question = Debian::DebConf::ConfigDb::getquestion($ARGV[0]);
if (defined $question) {
print $question->value() . "\n";
exit 0;
} else {
exit 1;
}
(and similar implementations for the other necessary functions.
db_set, db_reset, db_{un,}register, db_f[sg]et, db_subst, db_metaget,
and whatever. I'm not actually convinced that anything other than _get
is entirely necessary though. :-/)
. /usr/share/debconf/confmodule would then be replaced by:
PATH=$PATH:/usr/lib/debconf/bin
db_checkconfig
where _checkconfig runs the .config if necessary then exits.
postinsts would use FOO=`db_get foo/bar` instead of FOO=$RET, obviously.
Cheers,
aj, who seriously doesn't want to have to add lots of 3>/dev/null for
no useful reason
What does this gain us? It would be is horrendously slow. What's the bug you're trying to fix? You suggestion also just plain wouldn't work. Consider: FOO=`/usr/lib/debconf/bin/db_get foo/bar` db_get runs, and outputs "GET foo/bar". It then blocks waiting for something to read that. The backticks read it. db_get then blocks waiting for the frontend to respjnd with the value from the database. And block, and blocks, because the frontend never saw what it output. aj@azure.humbug.org.au wrote:
Speed is not an issue. First of all, how long it takes dpkg to run postinst's isn't really a major concern, especially considering where this would be used would previously have interfactive. Second, these things are only being run a couple of times, not in tight loops, so the time won't blow out even further. And most importantly, the only reason it's slow now (about half a second on my system), is because we're still using a hacked up prototype as our backend, the corresponding functionality in gconf takes about .04 of a second. /usr/lib/debconf/bin/db_get doesn't do the same thing as the db_get function defined by confmodule, though. It either prints out the value of foo/bar, and exits successfully, or does nothing, and exits unsuccessfully. Note that the confmodule stuff is only useful for interactive scripts, the only thing it buys us is not having to write some more code. The things it costs us is not clearly separating the two interfaces (eg, "you must not use db_input in postinsts" can't be conveniently enforced; and you have to deal with having the file descriptors all messed up compared to what you'd expect.) Cheers, aj
Anthony Towns wrote: Unfair, most of the overhead of the prototype is working around things dpkg cannot yet do. Although I'm suprised it's only 0.5 seconds. And it accesses the database directly, via the as-yet unspecified database access protocol? If so, this bug report clearly isn't going to go anywhere until said protocol is specced out. I wish someone would do that. I disagree. There are cases where you need to use commands other than GET in a postinst script. The most common case would be error recovery that requires user intervention. Go look at the realplayer postinst and tell me how I can write it without using INPUT. If separating the functions was a desirable goal, it could be easily done by providing a library that only included those functions (ie, db_get) that we expect would normally be used in a postinst. The messed up file descriptiors is a feature designed to ease the transition period a bit by not requiring that people stop their postinsts from echoing everything to stdout. It is not required, and it could even be turned off.
Read that as `Speeding it up is already necessary and already on the todo
list', not as `Your code sucks anyway, so it's not *my* fault it's slow'.
Or, alternately, read it as, `The code to speed it up is already written,
and integrating said code is already on the todo list'. Take your pick.
Yes, exactly. (Or close enough, or something)
Hmmm.
All postinsts should be noninteractive even in the event of errors, though.
(ObGospel)
I would've done it like so:
extract_fail () {
echo "Corrupt archive, aborting."
cd ..
rm -r $rvtmpdir
rm -f $DIR/$archive
exit 1
}
. If they've specified the wrong thing, they can use dpkg-reconfigure, if
they've not finished downloading they can do dpkg --configure realplayer.
In the meantime their install hasn't aborted waiting for help. Hell,
by the time they even notice, their download could well be finished.
Personally, I'd have had the .config have the code to validate the RPM
in the .config file ( ... | cpio --list >/dev/null, perhaps?).
I don't see any particular benefit to having the postinst be interactive
at all --- you can already do all your interaction in your .config file,
and there're already plenty of ways to do error recovery.
`messed up' == anything other than `0 = stdin, 1 = stdout, 2 = stderr,
and nothing else'. (As opposed to 0 = pipe from debconf, 1 = 2 = stderr,
3 = pipetodebconf, iirc).
Cheers,
aj
Anthony Towns wrote: Sorry, I know it's annoying, but it's also true. Well a postinst that noticed the archive was corrupt and continued without either prompting or exiting with an error code would be Just Evil. That's a good idea, I'll see if I can do that. I still think though that situations will arise where you have to do interactive error recovery. For example, you are installing a kernel and have said to create a boot disk and there's no disk in the drive. This is a crucial operation, because without the boot disk made, the system might not boot. Failing isn't an option, then. I don't understand what you would be using fd's 0 and 1 for. Clearly you're not reading from 0 since you use debconf and hanging for input in a postinst is bad. And all output to stdout by postinsts is frowned upon by policy.
And read that as `I suppose I could do that...'. :-/ Oh, sure. But if you're doing an apt-get dist-upgrade over a modem, having some of them abort, and the rest finish happily is better than having them all just sit there. I'd also, ideally, want to say something like: if db_capb local; then LOCAL=1 fi ... if [ "$LOCAL" ]; then if [ ! -e $FILE ]; then # ask again else # check if corrupt and ask again fi fi so you could do the configuring on a remote machine, and only do the local checking when you were actually local. (I've mentioned this before, but I'm not sure if I cam up with a good example at the time) Eh? if (write to disk); then if (no disk in drive); then exit 1 fi (write new kernel to floppy) fi (relink vmlinuz.old to current kernel) (relink vmlinuz to new kernel) exit 0 seems like it'd work fine? Well, the obvious problem with it is (presumably) that fd 3 is open which (presumably) causes either inetd or debconf to get confused and loop forever. In general, though, I'd rather have adding debconf support be just `add such-n-such at the top, and use such-n-such to get at variables, otherwise everything Just Works'. That's not quite the case right now, though. :-/ Cheers, aj
Anthony Towns wrote: But generally as soon as one of them aborts, your apt upgrade is teminated anyway. Capb does seem like a good way to implement this. You should just add db_stop to the end of your postinst.
Which isn't such an ideal situation that we want to keep it that way forever. (As I understand it, the problem is just that dpkg doesn't give any indication of whether it's worth continuing or not, not that Apt isn't able to deal with it) Which is pretty kludgy too, especially when I don't have any need for fd 3 anywhere anyway. Cheers, aj