Hi,
Sorry to say so, but capture.c is a real mess!!!
I'll try to rewrite it sometime.
For now I just made a little patch to make it use ng_attr_byid instead of
looping through the list by itself. (see attachment)
But, whatever way we do it, the bug stays the same. It just crashes in similar
code in ng_attr_byid now. But, this has an advantage: I couldn't inspect some
variables in Capture_AccessSettings (don't know why), but I can inspect the
equivalent variables in ng_attr_byid. So now I was able to get this
information out of gdb (removed some runs through the loop, and added some
comments):
Breakpoint 3, ng_attr_byid (dev=0x8c20664, id=8)
at utils/linux/capture/libng/grab-ng.c:246
246 if (attr->id == id)
(gdb) inspect attr
$48 = (struct ng_attribute *) 0x8be9810
(gdb) inspect *attr
$49 = {id = 1, priority = 0, name = 0xb7663b02 "norm",
group = 0x8bf47cc "Logitech QuickCam Pro 4000", type = 2, defval = 0,
choices = 0x8c813d0, min = 0, max = 0, points = 0,
read = 0xb77ceb50 <v4l2_read_attr>, write = 0xb77cee10 <v4l2_write_attr>,
handle = 0x8bf47a8, priv = 0x0, device_list = {next = 0x8be9898,
prev = 0xbfa176f4}, dev = 0xbfa176e4, global_list = {next = 0x0,
prev = 0x0}, app = 0x0}
(gdb) step
244 list_for_each(item, &dev->attrs) {
(gdb) step
245 attr = list_entry(item, struct ng_attribute, device_list);
(gdb) step
---------------------- skipping a lot of runs through the loop here --------
---------------------- Watch the device_list.next pointer now!!!! ----------
246 if (attr->id == id)
(gdb) inspect attr
$70 = (struct ng_attribute *) 0x8be9b80
(gdb) inspect *attr
$71 = {id = 16, priority = 2, name = 0x8bf5ec4 "Gain Level",
group = 0x8bf47cc "Logitech QuickCam Pro 4000", type = 1, defval = 0,
choices = 0x0, min = 0, max = 256, points = 0,
read = 0xb77ceb50 <v4l2_read_attr>, write = 0xb77cee10 <v4l2_write_attr>,
handle = 0x8bf47a8, priv = 0x8bf5ebc, device_list = {next = 0xbfa176f4,
prev = 0x8be9b68}, dev = 0xbfa176e4, global_list = {next = 0x0,
prev = 0x0}, app = 0x0}
(gdb) step
244 list_for_each(item, &dev->attrs) {
(gdb) step
245 attr = list_entry(item, struct ng_attribute, device_list);
(gdb) step
246 if (attr->id == id)
(gdb) inspect attr
$72 = (struct ng_attribute *) 0xbfa176bc
(gdb) inspect *attr
$73 = {id = -1210010412, priority = 134522568, name = 0x8c20620 "capture0",
group = 0xbfa17738 "ÈŠ\004\bæEØ·", type = -1210164927, defval = -1218031252,
choices = 0x0, min = -1079937224, max = -1218059300, points = 146933348,
read = 0x8, write = 0x1, handle = 0x1, priv = 0x804a6c8, device_list = {
next = 0x804a6c8, prev = 0x804a6c8}, dev = 0xb7dd9424, global_list = {
next = 0x18, prev = 0xb7e0b4d4}, app = 0x804a6c8}
--------------- I think the above is rubbish already, outside of list!!! -----
(gdb) step
244 list_for_each(item, &dev->attrs) {
(gdb) step
245 attr = list_entry(item, struct ng_attribute, device_list);
(gdb) step
246 if (attr->id == id)
(gdb) inspect attr
$74 = (struct ng_attribute *) 0x804a690
(gdb) inspect *attr
$75 = {id = 0, priority = 0, name = 0x0, group = 0x0, type = 0, defval = 0,
choices = 0x0, min = 0, max = 0, points = 0, read = 0, write = 0x9,
handle = 0x0, priv = 0x201, device_list = {next = 0x804a7e0, prev = 0x0},
dev = 0x1, global_list = {next = 0xb7e10180, prev = 0x804b230},
app = 0x804b240}
(gdb) step
244 list_for_each(item, &dev->attrs) {
(gdb) step
245 attr = list_entry(item, struct ng_attribute, device_list);
(gdb) step
246 if (attr->id == id)
(gdb) inspect attr
$76 = (struct ng_attribute *) 0x804a7a8
(gdb) inspect *attr
$77 = {id = 4096, priority = 4342,
name = 0x3000 <Address 0x3000 out of bounds>,
group = 0xfff <Address 0xfff out of bounds>, type = 0, defval = 0,
choices = 0x0, min = 134742120, max = 80, points = 475026859, read = 0,
write = 0x804f930, handle = 0x804b358, priv = 0x804b1f8, device_list = {
next = 0x65746600, prev = 0x35322372}, dev = 0x2e726500, global_list = {
next = 0x63626577, prev = 0x2e006d61}, app = 0x20392e31}
------ Okay, pointer out of rubbish points to rubbish... ----
(gdb) step
244 list_for_each(item, &dev->attrs) {
(gdb) step
245 attr = list_entry(item, struct ng_attribute, device_list);
(gdb) step
246 if (attr->id == id)
(gdb) inspect attr
$78 = (struct ng_attribute *) 0x657465c8
----------- Okay, there we are!!!! ------
(gdb) inspect *attr
Cannot access memory at address 0x657465c8
(gdb) bt full
#0 ng_attr_byid (dev=0x8c20664, id=8)
at utils/linux/capture/libng/grab-ng.c:246
item = (struct list_head *) 0x65746600
attr = (struct ng_attribute *) 0x657465c8
#1 0xb765e3dc in Capture_AccessSettings (clientData=0x0, interp=0x804a6c8,
objc=2, objv=0x804b384) at utils/linux/capture/capture.c:724
attr = Variable "attr" is not available.
(gdb) step
Program received signal SIGSEGV, Segmentation fault.
ng_attr_byid (dev=0x8c20664, id=8) at utils/linux/capture/libng/grab-ng.c:246
246 if (attr->id == id)
-------------------- end of gdb output -------------
Okay, that's the problem: a corrupted list pointer in libng!
I looked at the code for quite some time, but I couldn't find what causes this
problem.
Harry
*** capture.orig.c 2005-11-26 13:40:01.000000000 +0100
--- capture.c 2005-11-26 16:51:48.000000000 +0100
***************
*** 291,298 ****
int i;
struct capture_item* captureItem = NULL;
- int found = 0;
- struct list_head *item;
int channel;
--- 291,296 ----
***************
*** 327,341 ****
ng_dev_open(&dev);
// Search for the ATTR_ID_INPUT (channel) ng_attribute struct
! found = 0;
! list_for_each(item, &(&dev)->attrs) {
! attr = list_entry(item, struct ng_attribute, device_list);
! if (attr->id == ATTR_ID_INPUT) {
! found = 1;
! break;
! }
! }
! if (!found) attr = NULL;
// Set the channel using ng_attribute->write function
if(attr != NULL) {
--- 325,331 ----
ng_dev_open(&dev);
// Search for the ATTR_ID_INPUT (channel) ng_attribute struct
! attr = ng_attr_byid(&dev, ATTR_ID_INPUT);
// Set the channel using ng_attribute->write function
if(attr != NULL) {
***************
*** 377,382 ****
--- 367,373 ----
gfmt = fmt;
gfmt.fmtid = conv->fmtid_in;
gfmt.bytesperline = 0;
+
// Check if webcam supports the input colorspace of that converter
if (0 == dev.v->setformat(dev.handle,&gfmt)) {
fmt.width = gfmt.width;
***************
*** 658,665 ****
int set = 0;
int attribute;
int value;
- struct list_head *item;
- int found = 0;
proc = Tcl_GetStringFromObj(objv[0], NULL);
--- 649,654 ----
***************
*** 723,739 ****
Tcl_ResetResult(interp);
// Get the ng_attribute struct from the attribute id
! found = 0;
! list_for_each(item, &(&capItem->dev)->attrs) {
! attr = list_entry(item, struct ng_attribute, device_list);
! if (attr != NULL) {
! if (attr->id == attribute) {
! found = 1;
! break;
! }
! }
! }
! if (!found) attr = NULL;
// if we set, use attribute->write proc, else, use the attribute->read proc...
if(attr != NULL) {
--- 712,718 ----
Tcl_ResetResult(interp);
// Get the ng_attribute struct from the attribute id
! attr = ng_attr_byid(&(capItem->dev), attribute);
// if we set, use attribute->write proc, else, use the attribute->read proc...
if(attr != NULL) {