Ошибка Java: java.lang.IllegalArgumentException: сигнал, уже используемый VM: INT - PullRequest
5 голосов
/ 26 июня 2009

Я исследую проблему Java (с использованием 64-битной IBM JVM 1.4.2) в Red Hat Linux. Мне интересно, видел ли кто-нибудь это сообщение об ошибке раньше и знает, есть ли способ обойти эту проблему?

Источник:

import sun.misc.Signal;
import sun.misc.SignalHandler;

public class SignalTest extends Thread
{
    private static Signal signal = new Signal("INT");

    private static ShutdownHandler handler = new ShutdownHandler();

    private static class ShutdownHandler implements SignalHandler
    {
        public void handle(Signal sig)
        {
        }
    }

    public static void main(String[] args)
    {
        try
        {
            Signal.handle(signal, handler);
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }

        try { Thread.sleep(5000); } catch(Exception e) { e.printStackTrace(); }

        System.exit(0);
    }
}

Выход:

java.lang.IllegalArgumentException <Signal already used by VM: INT>
java.lang.IllegalArgumentException: Signal already used by VM: INT
at
com.ibm.misc.SignalDispatcher.registerSignal(SignalDispatcher.java:145)
at sun.misc.Signal.handle(Signal.java:199)
at xxx

Дополнительная информация:

Я обнаружил что-то странное. Причина сбоя в том, что я запускаю программу внутри сценария оболочки в качестве фонового процесса.

т.е. sigtest.sh:

#!/bin/bash
java -cp . SignalTest >> sigtest.log 2>&1 &

Если я запускаю программу из командной строки или удаляю «&» (т. Е. Сделаю ее процессом переднего плана внутри сценария оболочки), у нее не будет проблем ... Я не понимаю, почему это так.

Ответы [ 8 ]

3 голосов
/ 03 июля 2009

Это вполне может быть специфическая проблема реализации JVM. Мы используем недокументированный / неподдерживаемый API (sun.misc.Signal/SignalHandler), и поэтому никакой контракт на поведение API не гарантируется.

Реализация IBM JVM может делать вещи, связанные с обработкой сигналов, иначе, чем реализация SUN JVM, и, таким образом, вызывать эту проблему. Так что этот конкретный вариант использования работает в JVM SUN, но не в JVM IBM.

Но попробуйте следующее (я сам не могу попробовать):

Отключите все комбинации при запуске JVM с одним / двумя / тремя из этих параметров и при наличии возможных комбинаций значений.

  1. опция -Xrs указана / не указана
  2. свойство ibm.signalhandling.sigint установлено на true / false
  3. свойство ibm.signalhandling.rs установлено на true / false

(свойства были найдены через Google в нескольких дампах ошибок, но я не могу найти какую-либо конкретную документацию по ним)

Я не знаю, поддерживает ли IBM JVM этот специальный флаг, но вы также можете попробовать добавить его, что в SUN JVM кажется специфичным для некоторых проблем с обработчиками сигналов в linux / solaris

-XX:-AllowUserSignalHandlers

Или попробуйте использовать собственный обработчик сигнала, если это вариант для вас. Проверьте предоставленные образцы кода:

Хотя это не относится к вашей конкретной проблеме, статья IBM об обработке сигналов JVM (немного устаревшая, но все еще в основном правильная). С примерами для обработчиков сигналов собственного кода:

Откровения по обработке и завершению сигналов Java


Но я полагаю, что все это может оказаться бесполезным, поскольку реализация IBM JVM может полагаться на правильную работу SIGINT и, таким образом, никогда не даст вам возможности самостоятельно обработать SIGINT.

Btw. от описания до флага -Xrs Я понимаю, что на самом деле это может помешать вам делать то, что вы хотите. Там написано

Когда -Xrs используется на JVM от Sun, сигнальные маски для SIGINT, SIGTERM, SIGHUP и SIGQUIT не изменяются обработчики сигналов JVM и для этих сигналы не установлены .

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

2 голосов
/ 29 июня 2009

Попробуйте запустить JVM с опцией -Xrs, которая действительна для IBM JVM в соответствии с this в любом случае. Это может предотвратить конфликт.

РЕДАКТИРОВАТЬ: В ответ на ваше основное желание, посмотрите на:

Runtime.getRuntime (). AddShutdownHook (Thread)

Вы создаете подкласс объекта потока, и он будет запускаться как часть завершения работы (уберите -Xrs, чтобы это работало хорошо). Некоторые вещи (например, вызов halt в среде исполнения) могут помешать этому произойти, поэтому вам нужно знать о возможности того, что это просто не произойдет.

1 голос
/ 01 июля 2009

Как пишет Heinz Kabutz , сигналы, которые вы можете перехватить, зависят от операционной системы, на которой вы работаете, и, вероятно, от версии JVM. Если определенная комбинация os / jvm не позволяет зарегистрировать ваш сигнал, вам не повезло. Может быть, поможет настройка с os / vm.

Согласно вашему комментарию, добавление крюка отключения , как предложил Yishai, должно сработать.

0 голосов
/ 19 февраля 2016

Я также столкнулся с этой проблемой при работе с IBM JVM (64 бит) в Linux. Оказалось, что JVM чувствительна к маске сигналов процесса, который ее вызывает.

> grep Sig /proc/self/status
SigQ:   1/1030663
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000001001006
SigCgt: 0000000000000000

Обратите внимание, что бит для SIGINT (значение 2) установлен в SigIgn. При запуске IBM JVM с этой маской она отказывается устанавливать обработчик для SIGINT. Я решил эту проблему, запустив JVM через оболочку Python, которая сбрасывает обработчик SIGINT по умолчанию:

#!/usr/bin/env python

import os
import signal
import sys

signal.signal(signal.SIGINT, signal.SIG_DFL)

args = sys.argv[1:]
os.execv(args[0], args)

Первым аргументом оболочки является команда java, затем следуйте аргументам для JVM.

0 голосов
/ 05 декабря 2013

У меня тоже такая же проблема. Я запускаю программу Java из сценария ksh. Если я запускаю скрипт с учетной записью, которая имеет профиль csh т.е. в файле / etc / passwd

userx: *: 7260: 20 :: / Главная / userx: / USR / бен / CSH

Сценарий будет успешно запущен. Но если я запускаю его с учетной записью, отличной от профиля sh, он выдает ту же ошибку.

Итак, решение состоит в том, чтобы изменить ваш профиль пользователя unix на csh.

0 голосов
/ 06 июля 2009

Я заставил это работать, используя другую реализацию JVM (SuSE) вместо IBM. При работе с недокументированными функциями кажется, что JVM не очень последовательны в поведении.

0 голосов
/ 29 июня 2009

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

После добавления

System.out.println("Hello");

к сообщению дескриптора, я могу запустить класс следующим образом:

z@zolty:/tmp/so$ java SignalTest & sleep 1s && kill -2 $!
[1] 20467
z@zolty:/tmp/so$ Hello
z@zolty:/tmp/so$
z@zolty:/tmp/so$ java SignalTest
[1]+  Done             java SignalTest
0 голосов
/ 26 июня 2009

Исключение возникает из-за того, что на виртуальной машине уже установлен обработчик сигнала для SIGINT. Что вы можете / должны делать по этому поводу, зависит от контекста, в котором выдается это исключение.

...