# \[Bug:1.9\] context switch may occur during freeing io

**URL:** <https://www.ruby-forum.com/t/bug-1-9-context-switch-may-occur-during-freeing-io/143428>\
**Category:** Development\
**Created:** [July 18, 2008, 12:53pm UTC](https://www.ruby-forum.com/t/bug-1-9-context-switch-may-occur-during-freeing-io/143428 "2008-07-18T12:53:41Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yusuke\_ENDOH](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/c89c15/32.png) [@Yusuke\_ENDOH](https://www.ruby-forum.com/u/Yusuke_ENDOH)\
**Post date:** [July 18, 2008, 12:53pm UTC](https://www.ruby-forum.com/t/bug-1-9-context-switch-may-occur-during-freeing-io/143428/1 "2008-07-18T12:53:41Z")

</div>

e$B1sF#$G$9!#e(B

e$B0J2\<$N$h$&$Ke(B do\_select e$B$Ne(B blocking region e$B$Ke(B  
native\_thread\_yield e$B$re(B  
e$BF~$l$?\>e$G!"e(B

# Index: thread.c

— thread.c (revision 18124)  
+++ thread.c (working copy)  
@@ -2004,6 +2004,7 @@  
}  
#else  
BLOCKING\_REGION({

- native\_thread\_yield();  
result = select(n, read, write, except, timeout);  
if (result \< 0) lerrno = errno;  
}, ubf\_select, GET\_THREAD());

e$B0J2\<$r\<B9T$9$k$H!"$?$^$KMn$A$^$9!#e(B

$ ./ruby  
t = Thread.new do  
loop do  
w = IO.pipe.last  
w.sync = false  
w.write(“a” \* 1000)  
end  
end  
sleep 0.1  
Thread.new { }  
GC.start

-:3: [BUG] object allocation during garbage collection phase  
ruby 1.9.0 (2008-07-18 revision 18124) [i686-linux]

## – control frame ---------- c:0008 p:---- s:0015 b:0015 l:000014 d:000014 CFUNC :(null) c:0007 p:---- s:0013 b:0013 l:000012 d:000012 CFUNC :pipe c:0006 p:0013 s:0010 b:0010 l:000f88 d:000009 BLOCK -:3 c:0005 p:---- s:0009 b:0009 l:000008 d:000008 FINISH c:0004 p:---- s:0007 b:0007 l:000006 d:000006 CFUNC :loop c:0003 p:0007 s:0004 b:0004 l:000f88 d:000003 BLOCK -:2 c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH c:0001 p:---- s:0002 b:0002 l:000001 d:000001 TOP

## DBG\> : “-:3:in `(null)'" DBG> : "-:3:in`pipe’” DBG\> : “-:3:in `block (2 levels) in <main>'" DBG> : "-:2:in`loop’” DBG\> : “-:2:in `block in '” – backtrace of native function call (Use addr2line) – 0x8102065 0x812948e 0x81294eb 0x8061b3a 0x806953c 0x80fdc90 0x80fe0f2 0x807e180 0x807e982 0x8066852 0x8059e20 0x806a768 0x80f2efe 0x80f4f4c 0x80f7eb9 0x80fbdcb 0x80fc414 0x80fc962 0x8059fec 0x80f4063 0x80f4f4c 0x80f7eb9 0x80fbdcb 0x80fc414 0x80fc784 0x8106b9c 0x8106be1 0xb7f6a240 0xb7e9e49e

e$B%"%!\<%H$7$^$7$?e(B

e$B860x$O!"e(BT\_FILE e$B$,e(B GC e$B$5$l$k$H$-e(B

fptr\_finalize  
-\> io\_fflush  
-\> rb\_thread\_fd\_writable  
-\> rb\_thread\_wait\_fd\_rw  
-\> do\_select  
-\> BLOCKING\_REGION

e$B$H8F$S=P$7$,?J$s$G!"e(BGC  
e$BCf$KB\>$N%9%l%C%I$,F0$-=P$7$F$7$^$&$?$a$G$9!#e(B

e$B$3$NLdBj$,$J$+$C$?$H$7$F$b!“e(Bfptr\_finalize e$B$Ge(B io\_fflush  
e$B$9$k$N$Oe(B  
e$B%V%m%C%/$9$k2DG=@-$,$”$C$F$^$:$$5$$,$7$^$9!#$I$&$7$?$b$s$G$7$g$&!#e(B

---

<div class="post-metadata">

**Author:** ![Yusuke\_ENDOH](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/c89c15/32.png) [@Yusuke\_ENDOH](https://www.ruby-forum.com/u/Yusuke_ENDOH)\
**Post date:** [July 20, 2008, 2:05am UTC](https://www.ruby-forum.com/t/bug-1-9-context-switch-may-occur-during-freeing-io/143428/2 "2008-07-20T02:05:55Z")

</div>

e$B$J$+$@$G$9!#e(B

At Fri, 18 Jul 2008 19:47:28 +0900,  
Yusuke ENDOH wrote in [ruby-dev:35578]:

> e$B860x$O!"e(BT\_FILE e$B$,e(B GC e$B$5$l$k$H$-e(B
> 
> fptr\_finalize  
> -\> io\_fflush  
> -\> rb\_thread\_fd\_writable  
> -\> rb\_thread\_wait\_fd\_rw  
> -\> do\_select  
> -\> BLOCKING\_REGION
> 
> e$B$H8F$S=P$7$,?J$s$G!"e(BGC e$BCf$KB\>$N%9%l%C%I$,F0$-=P$7$F$7$^$&$?$a$G$9!#e(B

T\_DATAe$B$Ne(Bdfreee$B$He(Bfptr\_finalizee$B$Oe(Bdeferrede$B$K2s$7$^$7$g$&$+!#e(B

> e$B$3$NLdBj$,$J$+$C$?$H$7$F$b!“e(Bfptr\_finalize e$B$Ge(B io\_fflush e$B$9$k$N$Oe(B  
> e$B%V%m%C%/$9$k2DG=@-$,$”$C$F$^$:$$5$$,$7$^$9!#$I$&$7$?$b$s$G$7$g$&!#e(B

e$B$3$C$A$O$I$&$7$^$7$g$&$+$M$’!#e(B

# Index: gc.c

— gc.c (revision 18132)  
+++ gc.c (working copy)  
@@ -1324,5 +1324,5 @@ gc\_mark\_children(rb\_objspace\_t \*objspace  
}

-static void obj\_free(rb\_objspace\_t \*, VALUE);  
+static int obj\_free(rb\_objspace\_t \*, VALUE);

static void  
@@ -1402,9 +1402,7 @@ gc\_sweep(rb\_objspace\_t \*objspace)  
while (p \< pend) {  
if (!(p-\>as.basic.flags & FL\_MARK)) {

- if (p-\>as.basic.flags) {
- 

```
   obj_free(objspace, (VALUE)p);

```

- }
- if (need\_call\_final && FL\_TEST(p, FL\_FINALIZE)) {
- 

```
   p->as.free.flags = FL_MARK; /* remain marked */

```

- if (p-\>as.basic.flags && obj\_free(objspace, (VALUE)p) ||
- 

```
   need_call_final && FL_TEST(p, FL_FINALIZE)) {

```

- 

```
   p->as.free.flags |= FL_MARK; /* remain marked */
   p->as.free.next = final_list;
   final_list = p;

```

@@ -1470,5 +1468,5 @@ rb\_gc\_force\_recycle(VALUE p)  
}

-static void  
+static int  
obj\_free(rb\_objspace\_t \*objspace, VALUE obj)  
{  
@@ -1527,5 +1525,5 @@ obj\_free(rb\_objspace\_t \*objspace, VALUE  
}  
else if (RANY(obj)-\>as.data.dfree) {

- (\*RANY(obj)-\>as.data.dfree)(DATA\_PTR(obj));

- return 1;  
}  
}  
@@ -1542,5 +1540,5 @@ obj\_free(rb\_objspace\_t \*objspace, VALUE  
case T\_FILE:  
if (RANY(obj)-\>as.file.fptr) {

- 

```
 rb_io_fptr_finalize(RANY(obj)->as.file.fptr);

```

- 

```
 return 1;

```

}  
break;  
@@ -1571,5 +1569,5 @@ obj\_free(rb\_objspace\_t \*objspace, VALUE  
break;  
}

- return; /\* no need to free iv\_tbl \*/

- break; /\* no need to free iv\_tbl \*/

@@ -1584,4 +1582,6 @@ obj\_free(rb\_objspace\_t _objspace, VALUE  
RANY(obj)-\>as.basic.flags & T\_MASK, (void_)obj);  
}

- RANY(obj)-\>as.basic.flags &= ~T\_MASK;
- return 0;  
}

@@ -2010,4 +2010,12 @@ run\_final(rb\_objspace\_t _objspace, VALUE  
objid = rb\_obj\_id(obj); /_ make obj into id \*/  
rb\_thread\_critical = Qtrue;

- switch (RANY(obj)-\>as.basic.flags & T\_MASK) {
- 

```
 case T_DATA:

```

- (\*RANY(obj)-\>as.data.dfree)(DATA\_PTR(obj));
- break;
- 

```
 case T_FILE:

```

- rb\_io\_fptr\_finalize(RANY(obj)-\>as.file.fptr);
- break;
- }  
args[1] = 0;  
args[2] = (VALUE)rb\_safe\_level();

---

<div class="post-metadata">

**Author:** ![Yusuke\_ENDOH](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/c89c15/32.png) [@Yusuke\_ENDOH](https://www.ruby-forum.com/u/Yusuke_ENDOH)\
**Post date:** [July 21, 2008, 9:47am UTC](https://www.ruby-forum.com/t/bug-1-9-context-switch-may-occur-during-freeing-io/143428/3 "2008-07-21T09:47:29Z")

</div>

e$B$J$+$@$G$9!#e(B

At Sun, 20 Jul 2008 08:27:35 +0900,  
Nobuyoshi N. wrote in [ruby-dev:35594]:

> > e$B$H8F$S=P$7$,?J$s$G!"e(BGC e$BCf$KB\>$N%9%l%C%I$,F0$-=P$7$F$7$^$&$?$a$G$9!#e(B
> 
> T\_DATAe$B$Ne(Bdfreee$B$He(Bfptr\_finalizee$B$Oe(Bdeferrede$B$K2s$7$^$7$g$&$+!#e(B

ObjectSpacee$B$+$i8+$($F$7$^$&$H$^$:$$$N$G!"D{@5$G$9!#e(B

# Index: gc.c

— gc.c (revision 18139)  
+++ gc.c (working copy)  
@@ -1317,4 +1317,7 @@ gc\_mark\_children(rb\_objspace\_t \*objspace  
break;

- 

```
 case T_UNDEF:

```

- break;
- 

```
 default:

```

rb\_bug(“rb\_gc\_mark(): unknown data type 0x%lx(%p) %s”,  
@@ -1324,5 +1327,5 @@ gc\_mark\_children(rb\_objspace\_t \*objspace  
}

-static void obj\_free(rb\_objspace\_t \*, VALUE);  
+static int obj\_free(rb\_objspace\_t \*, VALUE);

static void  
@@ -1402,9 +1405,7 @@ gc\_sweep(rb\_objspace\_t \*objspace)  
while (p \< pend) {  
if (!(p-\>as.basic.flags & FL\_MARK)) {

- if (p-\>as.basic.flags) {
- 

```
   obj_free(objspace, (VALUE)p);

```

- }
- if (need\_call\_final && FL\_TEST(p, FL\_FINALIZE)) {
- 

```
   p->as.free.flags = FL_MARK; /* remain marked */

```

- if (p-\>as.basic.flags && obj\_free(objspace, (VALUE)p) ||
- 

```
   need_call_final && FL_TEST(p, FL_FINALIZE)) {

```

- 

```
   p->as.free.flags |= FL_MARK; /* remain marked */
   p->as.free.next = final_list;
   final_list = p;

```

@@ -1470,5 +1471,5 @@ rb\_gc\_force\_recycle(VALUE p)  
}

-static void  
+static int  
obj\_free(rb\_objspace\_t \*objspace, VALUE obj)  
{  
@@ -1527,5 +1528,7 @@ obj\_free(rb\_objspace\_t \*objspace, VALUE  
}  
else if (RANY(obj)-\>as.data.dfree) {

- (\*RANY(obj)-\>as.data.dfree)(DATA\_PTR(obj));

- RANY(obj)-\>as.basic.flags &= ~T\_MASK;
- RANY(obj)-\>as.basic.flags |= T\_UNDEF;
- return 1;  
}  
}  
@@ -1542,5 +1545,10 @@ obj\_free(rb\_objspace\_t \*objspace, VALUE  
case T\_FILE:  
if (RANY(obj)-\>as.file.fptr) {

- 

```
 rb_io_fptr_finalize(RANY(obj)->as.file.fptr);

```

- 

```
 rb_io_t *fptr = RANY(obj)->as.file.fptr;

```

- 

```
 RANY(obj)->as.basic.flags &= ~T_MASK;

```

- 

```
 RANY(obj)->as.basic.flags |= T_UNDEF;

```

- 

```
 RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;

```

- 

```
 RDATA(obj)->data = fptr;

```

- 

```
 return 1;

```

}  
break;  
@@ -1571,5 +1579,5 @@ obj\_free(rb\_objspace\_t \*objspace, VALUE  
break;  
}

- return; /\* no need to free iv\_tbl \*/

- break; /\* no need to free iv\_tbl \*/

@@ -1580,8 +1588,13 @@ obj\_free(rb\_objspace\_t \*objspace, VALUE  
break;

- 

```
 case T_UNDEF:

```

- break;
- 

```
 default:

```

rb\_bug(“gc\_sweep(): unknown data type 0x%lx(%p)”,  
RANY(obj)-\>as.basic.flags & T\_MASK, (void\*)obj);  
}
- RANY(obj)-\>as.basic.flags &= ~T\_MASK;
- return 0;  
}

@@ -1855,4 +1868,5 @@ os\_obj\_of(rb\_objspace\_t \*objspace, VALUE  
case T\_ICLASS:  
case T\_NODE:

- 

```
 case T_UNDEF:
   continue;
 case T_CLASS:

```

@@ -2010,4 +2024,7 @@ run\_final(rb\_objspace\_t _objspace, VALUE  
objid = rb\_obj\_id(obj); /_ make obj into id \*/  
rb\_thread\_critical = Qtrue;

- if ((RANY(obj)-\>as.basic.flags & T\_MASK) == T\_UNDEF) {
- (\*RANY(obj)-\>as.data.dfree)(DATA\_PTR(obj));
- }  
args[1] = 0;  
args[2] = (VALUE)rb\_safe\_level();

---

<div class="post-metadata">

**Author:** ![Yusuke\_ENDOH](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/c89c15/32.png) [@Yusuke\_ENDOH](https://www.ruby-forum.com/u/Yusuke_ENDOH)\
**Post date:** [July 25, 2008, 4:57pm UTC](https://www.ruby-forum.com/t/bug-1-9-context-switch-may-occur-during-freeing-io/143428/4 "2008-07-25T16:57:43Z")

</div>

e$B%A%1%C%He(B #293 e$B$,99?7$5$l$^$7$?!#e(B (by Nobuyoshi N.)

e$B%9%F!\<%?%9e(B Opene$B$+$ie(BClosede$B$KJQ99e(B  
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

## Applied in changeset r18221.

[http://redmine.ruby-lang.org/issues/show/293](http://redmine.ruby-lang.org/issues/show/293)
