2009年06月18日 request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その6) [長年日記]
_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その6)
request_module[net-pf-10]: waitpid(3788,...) failed, errno 1
の errno 1 は /usr/include/asm/errno.h より
#define EPERM 1 /* Operation not permitted */
を表していると思っていた。ところが /usr/src/linux/kernel/kmod.c より
178 int request_module(const char * module_name) 179 { 180 pid_t pid; 181 int waitpid_result; 182 sigset_t tmpsig; 183 int i; 184 static atomic_t kmod_concurrent = ATOMIC_INIT(0); 185 #define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */ 186 static int kmod_loop_msg; 187 188 /* Don't allow request_module() before the root fs is mounted! */ 189 if ( ! current->fs->root ) { 190 printk(KERN_ERR "request_module[%s]: Root fs not mounted\n", 191 module_name); 192 return -EPERM; 193 } 194 195 /* If modprobe needs a service that is in a module, we get a recursive 196 * loop. Limit the number of running kmod threads to max_threads/2 or 197 * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method 198 * would be to run the parents of this process, counting how many times 199 * kmod was invoked. That would mean accessing the internals of the 200 * process tables to get the command line, proc_pid_cmdline is static 201 * and it is not worth changing the proc code just to handle this case. 202 * KAO. 203 */ 204 i = max_threads/2; 205 if (i > MAX_KMOD_CONCURRENT) 206 i = MAX_KMOD_CONCURRENT; 207 atomic_inc(&kmod_concurrent); 208 if (atomic_read(&kmod_concurrent) > i) { 209 if (kmod_loop_msg++ < 5) 210 printk(KERN_ERR 211 "kmod: runaway modprobe loop assumed and stopped\n"); 212 atomic_dec(&kmod_concurrent); 213 return -ENOMEM; 214 } 215 216 pid = kernel_thread(exec_modprobe, (void*) module_name, 0); 217 if (pid < 0) { 218 printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid); 219 atomic_dec(&kmod_concurrent); 220 return pid; 221 } 222 223 /* Block everything but SIGKILL/SIGSTOP */ 224 spin_lock_irq(¤t->sigmask_lock); 225 tmpsig = current->blocked; 226 siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP)); 227 recalc_sigpending(current); 228 spin_unlock_irq(¤t->sigmask_lock); 229 230 waitpid_result = waitpid(pid, NULL, __WCLONE); 231 atomic_dec(&kmod_concurrent); 232 233 /* Allow signals again.. */ 234 spin_lock_irq(¤t->sigmask_lock); 235 current->blocked = tmpsig; 236 recalc_sigpending(current); 237 spin_unlock_irq(¤t->sigmask_lock); 238 239 if (waitpid_result != pid) { 240 printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n", 241 module_name, pid, -waitpid_result); 242 } 243 return 0; 244 }
240行〜241行が問題のエラーメッセージを出しているところなのだが、errnoに該当するのは -waitpid_result で、これは230行の waitpidのリターン値(-1)を符号反転したものに過ぎない。waitpidのリターン値が-1なのは単に「エラーで返ったよ」の印に過ぎず、真のエラーコードは errno に格納されているはず。なので、
239 if (waitpid_result != pid) { 240 #if 0 241 printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n", 242 module_name, pid, -waitpid_result); 243 #else 244 printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d realerrno %d\n", 245 module_name, pid, -waitpid_result, errno); 246 #endif 247 }
のようにして、カーネルをビルド中。
_ request_module[net-pf-10]: waitpid(3788,...) failed, errno 1 (その7)
本当の errno は
ECHILD 10 /* No child processes */
だった。
2.4系のスレッドの問題かもしれないが、はっきりとした事は言えない。とりあず
*** kernel/kmod.c.ORG 2009-06-18 01:09:00.000000000 +0900 --- kernel/kmod.c 2009-06-18 09:56:55.000000000 +0900 *************** *** 237,244 **** --- 237,251 ---- spin_unlock_irq(¤t->sigmask_lock); if (waitpid_result != pid) { + #if 0 printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n", module_name, pid, -waitpid_result); + #else + if (errno != ECHILD){ + printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d realerrno %d\n", + module_name, pid, -waitpid_result, errno); + } + #endif } return 0; }
みたいにして、ECHILDの時はメッセージを出さないようにした。ビルド&再起動して様子をみているけれど、非常に場当たり的だが問題なさそう。