LINUX.ORG.RU

Сообщения jek_

 

Два раза mprotect чтобы узнать атрибуты страницы стека....

Кошерно ли? Мне нужно в обработчике узнать, вызван ли данный SIGSEGV переполнением стека. Обработчик работает на альтернативном стеке. Берем из контекста ESP и EIP, узнаем по этой паре страницу, к которой случился доступ, а затем два раза mprotect на нее - узнаем атрибуты, затем выставляем staus quo.

Хорошо ли так делать?

Спасибо за помощь :)

jek_
()

Не понимаю, как обновить ядро в Gentoo... Help!...

Стоит Gentoo 2004.2. Хочу ядро обновить до 2.6.10-r6. Что говорить emerge? Скачал gentoo-sources-2.6.10-r6.ebuild, но что с ним делать? И, насколько я понимаю, оно захочет еще и linux26-headers-2.6.10-r6, но такого зверя вообще не существует...

В общем, погибаю, помогите!

Заранее спасибо!

jek_
()

C++: перегруженные new/delete не работают в shared libraries?!

Собственно, subj.

Если сделать такую библиотеку:

#include <stdio.h>
#include <stdlib.h>
void * operator new(size_t n)
{ 
  printf("operator new(%d)\n",n);
  return malloc(n); 
}
void operator delete(void* p)
{ 
  printf("operator delete(%X)\n",p);
  return free(p); 
}
class my_struct {
  char data[0x10000];
};
my_struct *mystr = new my_struct;
extern "C" {
 extern void Cleanup () {
        printf("cleaning up...\n");
        delete mystr;
 }
}

загрузить, поработать и выгрузить ее dlopen/dlsym/dlclose, операторы
new/delete заиспользуются вовсе не мои перегруженные, а стандартные.
как же быть, если мне позарез нужно перегрузить new/delete в моей
конкретной библиотеке?

Да, а в обычных екзешниках все мои new/delete работают...

jek_
()

Как в баше вычислять арифм. выражения с плавающей точкой?

sum=`expr $num + $sum`

работает только для целых...
если есть запятая или точка, то

expr: non-numeric argument
expr: syntax error
jek_
()

Ловля stack overflow

Вот такая проблема - нужно _всегда_ ловить stack overflow, причем нативный код может быть получен не только с помощью gcc, а как угодно, хоть самописный на ассемблере. Я посмотрел в info libc, там сказано, что сигнал SIGILL _может_ бросаться в случае переполнения стека. Не уточняется, что значит - может. Всегда ли он бросается, и всегда ли именно SIGILL, и именно с параметром ILL_BADSTK?

Есть ли вообще готовые методы ловли ситуации переполнения стека?

Спасибо!

jek_
()

Как лучше организовать автоматическое удаление файлов?

В виндах есть флаг FILE_FLAG_DELETE_ON_CLOSE, передаваемый в вызов CreateFile - новосозданный файл удаляется при завершении процесса. Как лучше сделать то же самое в линуксе?

jek_
()

Как испольуется первый гигабайт вирт. памяти?

Замечено, что при интенсивном расходе памяти via malloc & mmap память выделяется фактически начиная с 0x80000000 и забивается примерно до 0xC00000000, после чего очередной вызов mmap обламывается. Почему же выделение не происходит в первом гиге?

jek_
()

RedHat SRPM - как собрать?

Ни разу не приходилось... Есть редхатовый gcc в SRPM. Если сказать rpm --install на него, оно развернет в /usr/src/packages/SOURCES файл gcc-3.2-7....tar.bz2 и кучу patch-файлов. И все. Вопрос такой: а как же это все правильно скомпилировать, и чтобы все патчи правильно приложились?

Огромное спасибо за советы!

jek_
()

dlopen causes SEGFAULT

Hello All!

Я вот наткнулся на странную проблему, может быть, кто-нибудь знает, в
чем дело... Итак:

1) есть исходник shared library с инициализатором _init:

-------- mydll.c -----------------------------------
#include <dlfcn.h>
static void *myhandle;
void _init() {
    myhandle = dlopen("/lib/libc.so.6", RTLD_LAZY);
}
----------------------------------------------------

компилируется так:

gcc -Wall mydll.c -nostdlib -shared -o libmydll.so -ldl

2) есть программулина, которая грузит эту lybmydll.so:

-------- test.c ------------------------------------
#include <dlfcn.h>
#include <stdio.h>
int main() {
  char libname[] = "libmydll.so";
  void *lib = dlopen(libname, RTLD_LAZY);
  if(!lib) {
    printf("Cannot open library: %s\n", dlerror());
    return 1;
  }
  printf("OK!\n");
  return 0;
}
----------------------------------------------------

Компилируем программулину так:

gcc -g -c test.c -o test.o
gcc -g -o test test.o -ldl

Запускаем:

bash$ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
bash$ ./test
OK!

Все работает. А вот теперь внимание - компилируем по-другому:

gcc -g -c test.c -o test.o
gcc -g -o test test.o -static -lc -ldl

Запускаем:

bash$ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
bash$ ./test
Segmentation fault

Таким образом, при вызове dlopen из инициализатора все работает, если
екзешник собран динамическим, а если статически - все падает... Без
вызова dlopen опять-таки все в порядке.

Крэш происходит в динамическом загрузчике (/lib/ld-2.3.2.so). Где -
непонятно, собирать и инсталлить все хозяйство с отладкой слишком
опасно :(

В чем может быть дело?

Заранее спасибо!
jek_
()

Приоритеты потоков... help!

Я наткнулся на проблему с приоритетами тредов. Возьмем такой код:

#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sched.h>

unsigned int countA;
unsigned int countB;
const unsigned int MAX = 2000000000;

void *startA(void *a) {
    sleep(1);
    
    for(countA = 0; countA < MAX; countA++) {
        if(countA % 1024 == 0)
              printf("Thread A is working, countA = %d\n", countA);
    }

    printf("Thread A has ended: countA = %d, countB = %d\n", countA, countB);
    exit(0);
}


void *startB(void *a) {
    sleep(1);

    for(countB = 0; countB < MAX; countB++) {
        if(countB % 1024 == 0)
              printf("Thread B is working, countB = %d\n", countB);
    }

    printf("Thread B has ended: countA = %d, countB = %d\n", countA, countB);
    exit(0);
}


void check(int r) {
    printf("res = %d\n", r);
    if(r) {
       printf("error = %s\n", strerror(r));
       exit(0);
    }
}

int main() {
    struct sigaction act;
    pthread_t tA, tB;
    pthread_attr_t tA_attr, tB_attr;
    struct sched_param sch;
    int res;
    int MY_SCHED_POLICY = SCHED_FIFO;

    if(geteuid() != 0) {
         fprintf(stderr, "root expected\n");
         return -1;
    }

    MY_SCHED_POLICY = SCHED_FIFO;

    /// tA
    check(pthread_attr_init(&tA_attr));
    check(pthread_attr_setschedpolicy(&tA_attr, MY_SCHED_POLICY));

    /// tB
    check(pthread_attr_init(&tB_attr));
    check(pthread_attr_setschedpolicy(&tB_attr, MY_SCHED_POLICY));

    /// tA
    check(pthread_create(&tA, &tA_attr, &startA, NULL));

    sch.sched_priority = 55;
    check(pthread_setschedparam(tA, MY_SCHED_POLICY, &sch));

    /// tB
    check(pthread_create(&tB, &tB_attr, &startB, NULL));

    sch.sched_priority = 54;
    check(pthread_setschedparam(tB, MY_SCHED_POLICY, &sch));

    //
    sleep(10000000);

    printf("Thread C is exiting: countA = %d, countB = %d\n", countA, countB);
    
    return 0;
}

Тред с меньшим приоритетом вообще не увеличивает свой count. Почему? 
Я читал man sched_setscheduler, там предостерегают использовать 
приотритеты процессов, но подобная ситуация не описывается...

Подскажите, где я неправ.

Да, у меня Red Hat 8, kernel 2.6.20-19.8, LinuxThreads.

Заранее спасибо.
jek_
()

open(«/dev/null», ...) - fake stdin/stdout/stderr?

Вчера в одной приладе увидел вот такой код с комментарием (но без 
каких-либо дополнительных разъяснений):

/* Open fake stdin, stdout, stderr - just in case */
open("/dev/null", O_RDONLY);
open("/dev/null", O_WRONLY);
open("/dev/null", O_WRONLY);

Вопрос такой: зачем такое делается? Какое отношение имеют стандартные
каналы к /dev/null? Почему не сохраняются результирующие дескрипторы?

Заранее спасибо за информацию :)
jek_
()

Вызов poll рвется RT-сигналом, у которого стоит флаг SA_RESTART. Что делать?!

Ситуация примерно следующая. Есть мультитредовое приложение, работает
под NPTL only (LinuxThreads меня не интересует). На сигнал SIGRT_3
навешивается некоторое действие. При этом выставляется флаг sigaction
SA_RESTART. Один из потоков приложения садится на poll. Вся прилада
обрабатывает сетевые http-запросы (для их генерации я использую Apache
Benchmark, ab).

Так вот, через некоторое время очередной вызов poll возвращает -1,
errno = EINTR, и в логе strace случается такая запись:

poll([{fd=15, events=POLLIN}, {fd=30, events=POLLOUT}], 2, 0) = -1 EINTR (Interrupted system call)
--- SIGRT_3 (Real-time signal 2) @ 0 (0) ---

До этого в том же логе есть только записи

rt_sigaction(SIGRT_3, {0x404314e0, ~[RTMIN], SA_RESTART|SA_SIGINFO}, {SIG_DFL}, 8) = 0
..................................................
tgkill(12740, 12743, SIGRT_3) = 0
..................................................
poll([{fd=15, events=POLLIN, revents=POLLIN}, {fd=18, events=POLLOUT, revents=POLLOUT}, {fd=21, events=POLLIN, revents=POLLIN}, {fd=20, events=POLLIN, revents=POLLIN}, {fd=22, events=POLLIN}, {fd=19, events=POLLIN}], 6, 0) = 4
..................................................
--- SIGRT_3 (Real-time signal 2) @ 0 (0) ---
..................................................

То есть все идет как задумано...

Ну как может poll порваться-то? Я не просекаю... Может быть, это
баг в ядре? У меня 2.6.7, 2.6.8 - происходит одно и то же. NPTL
версии 0.61.

Заранее спасибо за любую помощь!

jek_
()

Мажорные номера версий у симлинков на so-libraries

Вот что интересно (может быть, вопрос совсем глупый, прошу сильно не
пинать, если так): какие правила линковки к shared library, если на
нее есть некоторое количество симлинков? Например, в RH8 есть такие
файлы:

/usr/lib/libz.so -> /usr/lib/libz.so.1.2.1.1
/usr/lib/libz.so.1 -> /usr/lib/libz.so.1.2.1.1
/usr/lib/libz.so.1.2.1.1

Спрашивается, что пропишется в executable, рожденный gcc-ом с
подключеной libz?

Проверка:

====ztest.c====
int main() {return 0;}
==============
$ gcc ztest.c -o ztest -lz
$ ldd ./ztest
        libz.so.1 => /usr/lib/libz.so.1 (0x00726000)
        libc.so.6 => /lib/tls/libc.so.6 (0x005de000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x005c5000)

objdump показываетс, что в секции NEEDED действительно прописано "libz.so.1".

Почему именно ".so.1"?

В новых дистрибах появилась новая версия libz (1.2.1, насколько я
понимаю). Появляется симлинк libz.so.2, и пропадает симлинк libz.so.
Так что если программа залинкована на libz.so, то скорее всего
работать она не будет. Опять же: как будет использоваться эта 
libz.so.2, если со старых программ на нее нет ссылки? Или libz.so.1=>
libz.so.2?

Так вот вопрос: как компилятор опереляет, к какому симлинку линковать?

Заранее большое спасибо за объяснения.
jek_
()

Изменения пределов user-space памяти в ядре 2.6.8 (или 2.6.6/2.6.7)

Ситуация следующая. Запускаем на ядре 2.6.5 или младше на i386
такую программку:

#include <stdio.h>
#include <sys/mman.h>
int main() {
  while(1) {
     void *p = mmap(NULL,0x100000,PROT_READ |PROT_WRITE|PROT_EXEC,
                   MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
     if(p==(void*)-1)
        break;
     printf("p = %X\n", p);
  }
  return 0;
}

Она заканчивает работу на последнем возвращенном адресе 0xBFE2F000,
что меньше 3-гигабайтного предела.

Запускаем ту же самую прогу на ядре 2.6.8. Последний адрес равен 0xFED00000,
что больше 3-гигабайтного предела.

Проблема в следующем: я никак не могу найти в ChangeLog-ах ядра
запись, указывающую на фикс, позволяющий адресоваться дальше 3 Gb.
Куда смотреть, чтобы понять, что вообще изменилось? 

Подскажите, плз. Заранее спасибо...
jek_
()

Вопрос про LOR и Mozilla - странная система администрирования паролей

Меня жутко раздражает такая странная особенность мозиллы, проявляющаяся,
как ни странно, только на сайте LOR: когда я создаю сообщение (или
отвечаю на чье-то), пользуясь своим зарегистрированным ником, мой пароль
и логин запоминается, а когда я снова создаю сообщение, он опять
запоминается, с тем же логином! Так что, при открытии любой страницы
форума LOR, вылазит мозилловское окошко, в котором написано "выберите
логин" и выбор из двух строк: 

jek_
jek_

Если я махну рукой и никак не разбирусь с password менеджером, в этой
таблице появится еще одна точно такая же запись. И так далее. Это 
окошко вылазит КАЖДЫЙ раз при открытии КАЖДОЙ новой LOR-ской страницы и ужасно
раздражает. Приходится каждый раз после добавления сообщения лезть в
password manager и удалять там лишнюю запись. Или вообще пользоваться
логином anonymous.

Скажите, это только у меня руки криво растут, или это мозилловский баг?
Или, может, с LOR-ом косяк?

Thanks in advance...
jek_
()

Как смотреть список непотвержденных новостей?

Вот, нужно мне :) Поэтому единственное, что приходит в голову - написать фуфловую новость, чтобы так проникнуть в этот самый список. Можно ли это сделать как-нибудь более честно?

jek_
()

Размер стека для exec.... Какой правильный?

У меня неожиданно возникла проблема: программа в main, сразу после
начала выполнения, выполняет fork-exec, предварительно установив
для себя размер стека 900'000 байт. Все прекрасно работало на многих
системах - RH8,9, Mandrake8,9.2,10, Fedora2. Но вдруг обнаружилось,
что на Fedora1 происходит SIGSEGV сразу после exec. Backtrace в
отладчике отсутствовал, текущая функция - _dl_sysinfo_int80.
Запускаемая программа даже не начинала исполняться (во
всяком случае, до ее main-а управление не доходило). Ничего не
помогало, пока я не догадался подкрутить rlimit для стека. Стоило
сделать его 2'000'000 байт, и все стало замечательно работать.
Повторюсь - это только на Fedora2. Вот и вопрос: в чему тут может
быть дело? Я хочу поковырять сорцы glibc от FC2, но вопрос несколько
более принципиальный - как управлять стеком? Какой остаток его будет
достаточен для fork-exec?
jek_
()

Вопрос про ptrace/SIGTRAP

Господа, я занимаюсь поделкой некоего подобия отладчика, и наткнулся
на одну неприятную проблему. Отлаживается многопотоковое приложение.
События типа breakpoint-ов и сигналов ловяться с помощью ptrace. Все
вроде бы прекрасно работает, но иногда вдруг в одном из потоков
отлаживаемого приложения случается сигнал SIGTRAP, и все мои проверки
на тип события проваливаются - SIGTRAP вызван не breakpoint-ом и не
каким-то сигналом. Процесс этот останавливается всгда в одном и том
же месте, а именно - в функции __pthread_sigsuspend. Код там такой:

libpthread.so$.__pthread_sigsuspend:
     4002FA20  push      ebp
     4002FA21  mov       ebp, esp
     4002FA23  mov       eax, dword ptr [ebp+08H]
     4002FA26  mov       ecx, 000000008H
     4002FA2B  push      ebx
     4002FA2C  mov       ebx, eax
     4002FA2E  mov       eax, 0000000B3H
---> 4002FA33  int       0FFFFFF80H
     4002FA35  pop       ebx
     4002FA36  pop       ebp
     4002FA37  ret

Стоп происходит в месте, отмеченном "--->".

Системный вызов с номером 0xb3 == 179 - это rt_sigsuspend.
Вот собственно и вопрос - почему rt_sigsuspend генерирует SIGTRAP?
Причем не под отладчиком никакого SIGTRAP никогда не летит, прилада
прекрасно работает.

Если этот сигнал просто проигнорировать, не отдавая процессу,
отлаживаемая программа повисает. Если отдать, то соответствующий
поток умрет и так же все накроется. Получается безвыходное положение,
так что нужно понять, отчего возникает этот сигнал.

Может быть, кто-нибудь занимался чем-то подобным? Буду весьма
благодарен за любую помощь.
jek_
()

Невыполнение exit()

У меня случается очень странная ситуация. Есть мультитредовая программа, работающая под LinuxThreads (NPTL не обсуждается). В ней есть обработчик Ctrl-C (SIGINT). Из этого обработчика зовется сначала pthread_cancel() для некоторых тредов, а затем exit(). Main-тред что-то печатает в цикле, и в это время пользователь нажимает Ctrl-C. В моем случае SIGINT всегда обрабатывается в main треде - это видно по PID-у. Вопреки всем ожиданиям, после вызова exit() main продолжает работу, которая была прервана по Ctrl-C! Все остальные потоки, кроме менеджера, умирают. То есть лог выглядит примерно так:

[pid 13801] Starting...
Running the runner 1
The runner 1 is working
The runner 1 is working
[pid 13801] The main thread is working
The runner 1 is working
The runner 1 is working
[pid 13801] The main thread is working
[pid 13801] SIGINT caught
[pid 13801] Killing threads... done
[pid 13801] calling exit...
[pid 13801] The main thread is working
[pid 13801] The main thread is working
[pid 13801] The main thread is working
[pid 13801] The main thread is working
[pid 13801] The main thread is working

Как же такое может быть?? У меня, честно говоря, ум за разум заходит... :(

jek_
()

Странная интерференция падающей программы с ulimit...

Столкнулся с такой проблемой: моя программа (A), время от времени вызывающая другую приладу (B), работает некоторое время, а потом случается следующее: она пытается в очередной раз вызвать B, но та падает, - статус fork->waitpid() говорит о том, что эта прилада B свалилась по сигналу SIGILL (то есть выполняется предикат WIFSIGNALED && WTERMSIG == SIGILL). Причем до вызова ее main(), похоже, дело даже не доходит.

Самое странно то, что, когда я попытался получить core файл и установил ulimit -Sc в unlimited, все заработало и работает прекрасно! Стоит сделать ulimit -Sc 0, как опять начинает случаться тот же глюк.

В чем тут может быть дело?

Заранее благодарен за советы....

jek_
()

RSS подписка на новые темы