函数源码

Linux Kernel

v5.5.9

Brick Technologies Co., Ltd

Source File:fs\coredump.c Create Date:2022-07-29 11:06:11
首页 Copyright©Brick

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
static int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
            struct core_state *core_state, int exit_code)
{
    struct task_struct *g, *p;
    unsigned long flags;
    int nr = -EAGAIN;
 
    spin_lock_irq(&tsk->sighand->siglock);
    if (!signal_group_exit(tsk->signal)) {
        mm->core_state = core_state;
        tsk->signal->group_exit_task = tsk;
        nr = zap_process(tsk, exit_code, 0);
        clear_tsk_thread_flag(tsk, TIF_SIGPENDING);
    }
    spin_unlock_irq(&tsk->sighand->siglock);
    if (unlikely(nr < 0))
        return nr;
 
    tsk->flags |= PF_DUMPCORE;
    if (atomic_read(&mm->mm_users) == nr + 1)
        goto done;
    /*
     * We should find and kill all tasks which use this mm, and we should
     * count them correctly into ->nr_threads. We don't take tasklist
     * lock, but this is safe wrt:
     *
     * fork:
     *  None of sub-threads can fork after zap_process(leader). All
     *  processes which were created before this point should be
     *  visible to zap_threads() because copy_process() adds the new
     *  process to the tail of init_task.tasks list, and lock/unlock
     *  of ->siglock provides a memory barrier.
     *
     * do_exit:
     *  The caller holds mm->mmap_sem. This means that the task which
     *  uses this mm can't pass exit_mm(), so it can't exit or clear
     *  its ->mm.
     *
     * de_thread:
     *  It does list_replace_rcu(&leader->tasks, ¤t->tasks),
     *  we must see either old or new leader, this does not matter.
     *  However, it can change p->sighand, so lock_task_sighand(p)
     *  must be used. Since p->mm != NULL and we hold ->mmap_sem
     *  it can't fail.
     *
     *  Note also that "g" can be the old leader with ->mm == NULL
     *  and already unhashed and thus removed from ->thread_group.
     *  This is OK, __unhash_process()->list_del_rcu() does not
     *  clear the ->next pointer, we will find the new leader via
     *  next_thread().
     */
    rcu_read_lock();
    for_each_process(g) {
        if (g == tsk->group_leader)
            continue;
        if (g->flags & PF_KTHREAD)
            continue;
 
        for_each_thread(g, p) {
            if (unlikely(!p->mm))
                continue;
            if (unlikely(p->mm == mm)) {
                lock_task_sighand(p, &flags);
                nr += zap_process(p, exit_code,
                            SIGNAL_GROUP_EXIT);
                unlock_task_sighand(p, &flags);
            }
            break;
        }
    }
    rcu_read_unlock();
done:
    atomic_set(&core_state->nr_threads, nr);
    return nr;
}