Linux学习笔记:pthread_getschedparam函数


在工作中遇到了一个问题,在Linux2.4.*的系统中调用pthread_getschedparam函数时,第一个参数指定为0系统不宕,

在Linux2.6的内核中调用该函数,第一个参数指定为0,则系统宕,原因是收到了SIGSEVG信号,也就是说程序访问的非法的地址。查了一晚上,应该是找到原因了。

首先看pthread_getschedparam函数的定义。

/*
* sched_getschedparam.c
*
* Description:
* POSIX thread functions that deal with thread scheduling.
*
* --------------------------------------------------------------------------
*
*      Pthreads-win32 - POSIX Threads Library for Win32
*      Copyright(C) 1998 John E. Bossom
*      Copyright(C) 1999,2005 Pthreads-win32 contributors
*
*      Contact Email: rpj@callisto.canberra.edu.au
*
*      The current list of contributors is contained
*      in the file CONTRIBUTORS included with the source
*      code distribution. The list can also be seen at the
*      following World Wide Web location:
*      http://sources.RedHat.com/pthreads-win32/contributors.html
*
*      This library is free software; you can redistribute it and/or
*      modify it under the terms of the GNU Lesser General Public
*      License as published by the Free Software Foundation; either
*      version 2 of the License, or (at your option) any later version.
*
*      This library is distributed in the hope that it will be useful,
*      but WITHOUT ANY WARRANTY; without even the implied warranty of
*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*      Lesser General Public License for more details.
*
*      You should have received a copy of the GNU Lesser General Public
*      License along with this library in the
file COPYING.LIB;
*
    if not, write to the Free Software Foundation, Inc.,
*      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/

#include "pthread.h"
#include "implement.h"
#include "sched.h"

int
pthread_getschedparam (pthread_t thread, int *policy,
       struct sched_param *param)
{
  int result;

  /* Validate the thread id. */
  result = pthread
_kill (thread, 0);
  if (0 != result)
    {
      return result;
    }

  /*
   * Validate the p
olicy and param args.
  * Check that a policy constant wasn't passed rather than &policy.
   */
  if (policy <= (int *) SCHED_MAX || param == NULL)
    {
      return EINVAL;
    }

  /* Fill out the policy. */
  *policy = SCHED_OTHER;

  /*
   * This function must re
turn the priority value set by
   * the most recent pthread_setschedparam() or pthread_create()
   * for the target thread. It must not return the actual thread
   * priority as altered by any system priority adjustments etc.
   */
  param->sched_priority = ((ptw32_thread_t *)thread.p)->sched_priority;

  return 0;
}
函数首先调用了pthread_kill函数,在查一下pthread_kill的定义。

/** Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.

02    This file is part of the GNU C Library.
03    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
04   
05    The GNU C Library is free software; you can redistribute it and/or
06    modify it under the terms of the GNU Lesser General Public
07    License as published by the Free Software Foundation; either
08    version 2.1 of the License, or (at your option) any later version.
09   
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14   
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19   
20 #include <errno.h>
21 #include <signal.h>
22 #include <pthreadP.h>
23 #include <tls.h>
24 #include <sysdep.h>
25 #include <kernel-features.h>
26   
27   
28 int
29 __pthread_kill (threadid, signo)
30      pthread_t threadid;
31      int signo;
32 {
33   struct pthread *pd = (struct pthread *) threadid;
34   
35   /** Make sure the descriptor is valid.  */
36   if (DEBUGGING_P && INVALID_TD_P (pd))
37     /** Not a valid thread handle.  */
38     return ESRCH;
39   
40   /** Force load of pd->tid into local variable or register.  Otherwise
41      if a thread exits between ESRCH test and tgkill, we might return
42      EINVAL, because pd->tid would be cleared by the kernel.  */
43   pid_t tid = atomic_forced_read (pd->tid);
44   if (__builtin_expect (tid <= 0, 0))
45     /** Not a valid thread handle.  */
46     return ESRCH;
47   
48   /** Disallow sending the signal we use for cancellation, timers, for
49      for the setxid implementation.  */
50   if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID)
51     return EINVAL;
52   
53   /** We have a special syscall to do the work.  */
54   INTERNAL_SYSCALL_DECL (err);
55   
56   /** One comment: The PID field in the TCB can temporarily be changed
57      (in fork).  But this must not affect this code here.  Since this
58      function would have to be called while the thread is executing
59      fork, it would have to happen in a signal handler.  But this is
60      no allowed, pthread_kill is not guaranteed to be async-safe.  */
61   int val;
62 #if __ASSUME_TGKILL
63   val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
64               tid, signo);
65 #else
66 # ifdef __NR_tgkill
67   val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
68               tid, signo);
69   if (INTERNAL_SYSCALL_ERROR_P (val, err)
70       && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
71 # endif
72     val = INTERNAL_SYSCALL (tkill, err, 2, tid, signo);
73 #endif
74   
75   return (INTERNAL_SYSCALL_ERROR_P (val, err)
76       ? INTERNAL_SYSCALL_ERRNO (val, err) : 0);
77 }
78 strong_alias (__pthread_kill, pthread_kill)

从中可以看到,在pthread_kill中,

if (DEBUGGING_P && INVALID_TD_P (pd))

37     /** Not a valid thread handle.  */
38     return ESRCH;

首先进行了判断,但是很有可能DEBUGGING_P宏没定义,所以程序就跳了过去,

然后再

43   pid_t tid = atomic_forced_read (pd->tid);
处访问了NULL指针,所以程序宕了。

相关内容