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: [email protected]
*
*      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的定义。

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

从中可以看到,在pthread_kill中,

if <font face="Courier New">(DEBUGGING_P && INVALID_TD_P (pd)) </font>

<font face="Courier New">37</font>    /** Not a valid thread handle.  */
<font face="Courier New">38</font>    return <font face="Courier New">ESRCH; </font>

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

然后再

<font face="Courier New">43</font>  pid_t tid = atomic_forced_read (pd->tid);
处访问了NULL指针,所以程序宕了。

相关推荐