kmod & error -512

Greg Zornetzer (gaz@andrew.cmu.edu)
Fri, 12 Jun 1998 17:56:58 -0400 (EDT)


Hi everyone,
Because of the problems some people have been having with kmod getting
waitpid error -512, I did a little looking. -512 is -ERESTARTSYS, which
acording to the waitpid manpage, occurs when an unblocked signal forces
the process out of the wait loop.
This can be reliably reproduced using by building the module modtest.o
(source included below). It basically waits for 20 seconds in its
init_module. To reproduce the problem, compile the module, place it in
/lib/module/<kernelversion>/misc, run a depmod -a, and alias char-major-14
to modtest. Now try cp'ing a file to /dev/audio. The process will hang
for 20 seconds while it waits for the module to finish initializing. If
you send the cp process a SIGUSR1, it will immediately return, and the
waitpid error will be in your syslog.

My solution to this problem is to add code in request_module to block all
signals by sigfillsetting current->blocked, and then restore
current->blocked after the waitpid is done. This ensures that we won't
have problems with unblocked signals while waiting on modprobe. I've
tested this on ix86 and it seems to correct the problem, but I seem to
remember weirdness with the alpha and signal manipulations, so this might
not work on alphas. Diff against stock 2.1.105 included below. It may
require some modification to patch against Alan's recent kernels, as they
contain an additional fix to kmod to prevent oopsing if the root fs hasn't
been mounted (Ben - could this be part of your problem?).

Anyway, the diff seems to have the proper behavior, but it might not be
done the Right Way(tm).
Comments?

Greg Zornetzer - gaz+@andrew.cmu.edu
"Light shines brightest in the darkest night"
http://www.contrib.andrew.cmu.edu/~gaz

--------------------start of modtest.c-----------
#include <linux/module.h>
#include <asm/delay.h>
#include <linux/sched.h>

int init_module (void)
{
unsigned long curr_jif, target_jif;
curr_jif = jiffies;
target_jif = curr_jif + 20*HZ;
while(jiffies < target_jif)
schedule();
return(0);
}

void cleanup_module(void)
{

}

---------------end of modtest.c--------------
--------------------start of kmodfix.diff----------
--- linux/kernel/kmod.c~ Sun Jun 7 21:04:38 1998
+++ linux/kernel/kmod.c Fri Jun 12 12:21:40 1998
@@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/unistd.h>
+#include <linux/signal.h>
#include <asm/smp_lock.h>
#include <asm/uaccess.h>

@@ -92,6 +93,15 @@
{
int pid;
int waitpid_result;
+ sigset_t temp;
+
+
+ spin_lock_irq(&current->sigmask_lock);
+ memcpy(&temp,&current->blocked, sizeof(sigset_t));
+ sigfillset(&current->blocked);
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+

pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS);
if (pid < 0) {
@@ -103,5 +113,16 @@
printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n",
pid, waitpid_result);
}
+
+ spin_lock_irq(&current->sigmask_lock);
+ memcpy(&current->blocked, &temp, sizeof(sigset_t));
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+
return 0;
}
--------end of kmodfix.diff----------

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu