1 A script may close the descriptor of a handle without delete() and open the 2 same path again, which yields the same number, device and inode. If another 3 descriptor keeps the old file open, epoll still reports it to the old 4 handle. Deleting the old handle must not remove the epoll entry of a handle 5 that watches the new file. 6 7 -- Testcase -- 8 {% 9 import * as uloop from 'uloop'; 10 import * as fs from 'fs'; 11 12 uloop.init(); 13 14 let dir = fs.mkdtemp(); 15 let path = dir + '/fifo'; 16 17 system(['mkfifo', path]); 18 19 function run() { 20 uloop.timer(50, () => uloop.end()); 21 uloop.run(); 22 } 23 24 let old_file = fs.open(path, 'r+'); 25 let old_fileno = old_file.fileno(); 26 let old_events = 0; 27 let old_handle = uloop.handle(old_file, () => old_events++, uloop.ULOOP_READ); 28 29 fs.dup2(old_fileno, 100); 30 old_file.close(); 31 32 let file = fs.open(path, 'r+'); 33 let events = 0; 34 35 uloop.handle(file, () => { 36 events++; 37 file.read(1); 38 }, uloop.ULOOP_READ); 39 40 printf("reused: %s\n", file.fileno() == old_fileno); 41 printf("delete: %s\n", old_handle.delete()); 42 43 for (let i = 0; i < 2; i++) { 44 file.write('x'); 45 file.flush(); 46 run(); 47 } 48 49 printf("old handle: %d, new handle: %d\n", old_events, events); 50 51 fs.fdopen(100).close(); 52 fs.unlink(path); 53 fs.rmdir(dir); 54 uloop.done(); 55 %} 56 -- End -- 57 58 -- Expect stdout -- 59 reused: true 60 delete: true 61 old handle: 0, new handle: 2 62 -- End -- 63 64 65 When nothing watches the reopened file, the removal of the old handle fails. 66 The old handle must then stay allocated for epoll, which still reports the 67 old file to it. 68 69 -- Testcase -- 70 {% 71 import * as uloop from 'uloop'; 72 import * as fs from 'fs'; 73 74 uloop.init(); 75 76 let dir = fs.mkdtemp(); 77 let path = dir + '/fifo'; 78 79 system(['mkfifo', path]); 80 81 let old_file = fs.open(path, 'r+'); 82 let old_fileno = old_file.fileno(); 83 let old_events = 0; 84 let handle = uloop.handle(old_file, () => old_events++, uloop.ULOOP_READ); 85 86 fs.dup2(old_fileno, 100); 87 old_file.close(); 88 89 let file = fs.open(path, 'r+'); 90 91 printf("reused: %s\n", file.fileno() == old_fileno); 92 printf("delete: %s\n", handle.delete()); 93 94 handle = null; 95 gc(); 96 97 file.write('x'); 98 file.flush(); 99 uloop.timer(50, () => uloop.end()); 100 uloop.run(); 101 102 printf("old handle: %d\n", old_events); 103 104 fs.fdopen(100).close(); 105 file.close(); 106 fs.unlink(path); 107 fs.rmdir(dir); 108 uloop.done(); 109 %} 110 -- End -- 111 112 -- Expect stdout -- 113 reused: true 114 delete: true 115 old handle: 0 116 -- End -- 117 118 -- Platform -- 119 Linux 120 -- End -- 121 122 123 uloop.done() closes the epoll instance, so it unregisters all handles. 124 They are released like handles whose descriptor uloop removed, and a 125 later delete() does not touch a new registration of the same number. 126 127 -- Testcase -- 128 {% 129 import * as uloop from 'uloop'; 130 import * as fs from 'fs'; 131 132 uloop.init(); 133 134 let fds = fs.pipe(); 135 let base = gc('count'); 136 let old_handle = uloop.handle(fds[0], () => null, uloop.ULOOP_READ); 137 138 uloop.handle(fds[1], () => null, uloop.ULOOP_WRITE); 139 uloop.done(); 140 gc(); 141 142 printf("dropped handle freed: %s\n", gc('count') - base == 2); 143 144 uloop.init(); 145 146 let events = 0; 147 148 uloop.handle(fds[0], () => { 149 events++; 150 fds[0].read(1); 151 uloop.end(); 152 }, uloop.ULOOP_READ); 153 154 printf("delete: %s\n", old_handle.delete()); 155 old_handle = null; 156 157 fds[1].write('x'); 158 fds[1].flush(); 159 160 let timer = uloop.timer(200, () => uloop.end()); 161 162 uloop.run(); 163 timer.cancel(); 164 timer = null; 165 166 printf("events: %d\n", events); 167 168 uloop.done(); 169 gc(); 170 printf("alive: %d\n", gc('count') - base); 171 %} 172 -- End -- 173 174 -- Expect stdout -- 175 dropped handle freed: true 176 delete: true 177 events: 1 178 alive: 0 179 -- End --
This page was automatically generated by LXR 0.3.1. • OpenWrt