Re: Bug#468075: this bug/#468075 - sudo: system freeze
On Thu, Mar 20, 2008 at 12:24:17PM -0400, Justin Pryzby <justinpryzby@users.sourceforge.net> was heard to say:
> On Wed, Mar 19, 2008 at 06:31:13PM -0700, Daniel Burrows wrote:
> > Most likely some critical part of your X session wanted to access the
> > disk, and it was blocked out by apt. I'm not sure how to confirm this;
> > on Windows there are ways of monitoring file accesses across the system
> > (so you could see which programs were contending with apt for the disk
> > and how long they got blocked), but I don't know of any equivalent for
> > Linux.
> I don't think it's disk IO related. Having run this command very
> often, all my Packages files are cached at various layers, and
> (despite having a not-recent machine with a slow disk and "only" 256MB
> RAM) the drive heads seem to be inactive during this interval.
That's probably right.
> I still think there's some problem somewhere between apt and the
> kernel. ptracing aptitude might reasonably cause a behavior change
> due to scheduling or such, but that still leaves a fair amount of
> observed behavior unexplained.
It might be triggered by apt, but it's the kernel's job to manage
user-space processes so they don't interfere with each other.
The attached program test.c, when run as root, will freeze the desktop
in the same way that "aptitude safe-upgrade" does. All it does is mmap()
two files (in fact, the apt package cache), then read from non-sequential
locations in them. That last bit is important: if I read sequentially,
the effect doesn't occur. If I run the program as a normal user, the
effect still doesn't occur.
This isn't dependent on the use of mmap(). I've attached a test2.c
that does exactly the same thing as test.c, but using read() system
calls. It freezes the desktop too -- but for longer, since it's
inefficiently reading one byte at a time.
Interestingly, if I run these on a text console, other text consoles
and the programs running in them are unaffected. Only X suffers a
complete freeze.
Anyway, I'm inclined to reassign this to the kernel. A user program
shouldn't trash the system by doing jumpy I/O.
Daniel
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int fd = open("/var/cache/apt/pkgcache.bin", O_RDONLY);
int fd2 = open("/var/cache/apt/srcpkgcache.bin", O_RDONLY);
struct stat buf1, buf2;
char *where1, *where2;
int i;
int tmp = 0;
unsigned int loc = 0;
if(fstat(fd, &buf1) != 0)
return -1;
if(fstat(fd2, &buf2) != 0)
return -1;
where1 = (char*)mmap(NULL, buf1.st_size, PROT_READ, MAP_SHARED, fd, 0);
where2 = (char*)mmap(NULL, buf2.st_size, PROT_READ, MAP_SHARED, fd, 0);
if(where1 == NULL || where2 == NULL)
return -1;
for(i = 0; i < buf1.st_size; ++i)
{
loc = ((loc + 10) * (buf1.st_size - 1)) % buf1.st_size;
tmp += where1[loc];
}
for(i = 0; i < buf2.st_size; ++i)
{
loc = ((loc + 10) * (buf2.st_size - 1)) % buf2.st_size;
tmp += where2[loc];
}
return 0;
}
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int fd = open("/var/cache/apt/pkgcache.bin", O_RDONLY);
int fd2 = open("/var/cache/apt/srcpkgcache.bin", O_RDONLY);
struct stat buf1, buf2;
int i;
int tmp = 0;
unsigned int loc = 0;
char buf[1];
if(fstat(fd, &buf1) != 0)
return -1;
if(fstat(fd2, &buf2) != 0)
return -1;
for(i = 0; i < buf1.st_size; ++i)
{
loc = ((loc + 10) * (buf1.st_size - 1)) % buf1.st_size;
lseek(fd, loc, SEEK_SET);
read(fd, buf, 1);
tmp += buf[0];
}
for(i = 0; i < buf2.st_size; ++i)
{
loc = ((loc + 10) * (buf2.st_size - 1)) % buf2.st_size;
lseek(fd, loc, SEEK_SET);
read(fd, buf, 1);
tmp += buf[0];
}
return 0;
}
Reply to: