Run userspace process from tasklet

2

Hello I am trying to run userspace process using call_usermodehelper_exec from tasklet that is created in kernel module for ARM board (from Olimex) with Allwinner SOC.

my code is prety simple:

#include <linux/kernel.h>
#include <linux/module.h>
char my_tasklet_data[]="tasklet executed";

static int umh_test(void)
{
  struct subprocess_info *sub_info;
  char *argv[] = { "/usr/bin/logger", "help!", NULL };
  static char *envp[] = {
    "HOME=/",
    "TERM=linux",
    "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };

  sub_info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC);
  if (sub_info == NULL) return -ENOMEM;

  return call_usermodehelper_exec(sub_info, UMH_WAIT_PROC);
}

void my_tasklet_function(unsigned long data)
{
  printk(KERN_INFO "%s\n", (char *)data);

  umh_test();

  return;
}

DECLARE_TASKLET(my_tasklet, my_tasklet_function,
            (unsigned long) &my_tasklet_data);

static int __init my_tasklet_init(void)
{
  tasklet_schedule(&my_tasklet);

  return 0;
}
module_init(my_tasklet_init);

static void __exit my_tasklet_cleanup(void)
{
  tasklet_kill(&my_tasklet);
}
module_exit(my_tasklet_cleanup);

after insmod tasklet.ko tasklet is executed and more over /usr/bin/logger is called, but I got also nasty kernel error like this:

[  969.327698] tasklet executed
<3>BUG: scheduling while atomic: ksoftirqd/0/3/0x00000102
[  969.335769] BUG: scheduling while atomic: ksoftirqd/0/3/0x00000102
<d>Modules linked in:[  969.343861] Modules linked in:root@a20-olimex:~#tasklet(O) tasklet(O) disp_ump disp_ump mali_drm mali_drm cpufreq_powersave cpufreq_powersave cpufreq_stats cpufreq_stats drm drm cpufreq_userspace cpufreq_userspace cpufreq_conservative cpufreq_conservative mali mali g_ether g_ether pwm_sunxi pwm_sunxi sun4i_csi0 sun4i_csi0 videobuf_dma_contig videobuf_dma_contig videobuf_core videobuf_core gt2005 gt2005 sun4i_keyboard sun4i_keyboard ledtrig_heartbeat ledtrig_heartbeat leds_sunxi leds_sunxi led_class led_class sunxi_emac sunxi_emac sunxi_gmac sunxi_gmac sunxi_cedar_mod sunxi_cedar_mod 8192cu 8192cu ump ump lcd lcd [last unloaded: tasklet] [last unloaded: tasklet]

[<c0015058>] (unwind_backtrace+0x0/0x134) from [<c058455c>] (__schedule+0x744/0x7d0)
[  969.410844] [<c0015058>] (unwind_backtrace+0x0/0x134) from [<c058455c>] (__schedule+0x744/0x7d0)
[<c058455c>] (__schedule+0x744/0x7d0) from [<c0582a20>] (schedule_timeout+0x1b8/0x220)
[  969.427299] [<c058455c>] (__schedule+0x744/0x7d0) from [<c0582a20>] (schedule_timeout+0x1b8/0x220)
[<c0582a20>] (schedule_timeout+0x1b8/0x220) from [<c0583c04>] (wait_for_common+0xe4/0x138)
[  969.444267] [<c0582a20>] (schedule_timeout+0x1b8/0x220) from [<c0583c04>] (wait_for_common+0xe4/0x138)
[<c0583c04>] (wait_for_common+0xe4/0x138) from [<c0049dc0>] (call_usermodehelper_exec+0x140/0x154)
[  969.462267] [<c0583c04>] (wait_for_common+0xe4/0x138) from [<c0049dc0>] (call_usermodehelper_exec+0x140/0x154)
[<c0049dc0>] (call_usermodehelper_exec+0x140/0x154) from [<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet])
[  969.482096] [<c0049dc0>] (call_usermodehelper_exec+0x140/0x154) from [<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet])
[<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet]) from [<c003c800>] (tasklet_action+0x98/0x134)
[  969.502110] [<bf1c6050>] (my_tasklet_function+0x50/0x58 [tasklet]) from [<c003c800>] (tasklet_action+0x98/0x134)
[<c003c800>] (tasklet_action+0x98/0x134) from [<c003c9d4>] (__do_softirq+0xd4/0x168)
[  969.519768] [<c003c800>] (tasklet_action+0x98/0x134) from [<c003c9d4>] (__do_softirq+0xd4/0x168)
[<c003c9d4>] (__do_softirq+0xd4/0x168) from [<c003cb58>] (run_ksoftirqd+0xf0/0x1bc)
[  969.535943] [<c003c9d4>] (__do_softirq+0xd4/0x168) from [<c003cb58>] (run_ksoftirqd+0xf0/0x1bc)
[<c003cb58>] (run_ksoftirqd+0xf0/0x1bc) from [<c00513a4>] (kthread+0x90/0x94)
[  969.551513] [<c003cb58>] (run_ksoftirqd+0xf0/0x1bc) from [<c00513a4>] (kthread+0x90/0x94)
[<c00513a4>] (kthread+0x90/0x94) from [<c000f4b8>] (kernel_thread_exit+0x0/0x8)
[  969.566739] [<c00513a4>] (kthread+0x90/0x94) from [<c000f4b8>] (kernel_thread_exit+0x0/0x8)

I try find similar problems because I am learning driver-development but all I have found was problem related to, lets call it kernel broken builds. I use own build of kernel, and I don't exclude that can be kernel related, but if someone is new with some topic he make sure that code has not any reprehensible error.

So any help will be appreciated

c
linux
linux-kernel
arm
linux-device-driver
asked on Stack Overflow Oct 13, 2015 by (unknown user) • edited Oct 13, 2015 by (unknown user)

2 Answers

3

The comment on call_usermodehelper_exec says in part:

 * @wait: wait for the application to finish and return status.
 *        when UMH_NO_WAIT don't wait at all, but you get no useful error back
 *        when the program couldn't be exec'ed. This makes it safe to call
 *        from interrupt context.

Calling from a tasklet is, in effect, an interrupt context so you cannot wait there. That is, you cannot block, because there is no task context with which to block. (This is what "scheduling while atomic" is telling you.)

You'll either need to work with a process context part, or you'll need to use UMH_NO_WAIT instead of UMH_WAIT_PROC. For example, you could have made the usermode helper call with UMH_WAIT_PROC from my_tasklet_init because there you have a task context.

answered on Stack Overflow Oct 13, 2015 by Gil Hamilton
1

Tasklet is executed in soft-irq context, so cannot sleep (call schedule function).

Usermode helper, from the other side, can sleep(like any other userspace code).

That's why you get BUG: scheduling while atomic message.

answered on Stack Overflow Oct 13, 2015 by Tsyvarev

User contributions licensed under CC BY-SA 3.0