'ROS Error. "Error processing request: signal only works in main thread"

I am working with Robot Operating System (ROS) and am attempting to make a server/client where the server will boot up ROS nodes that are specified by the client. To perform the "boot up" I am using roslaunch based on the recommendations found here: http://wiki.ros.org/roslaunch/API%20Usage

I can run the roscore in a window and then I can run the server which boots up fine. However, as soon as I try to send the node names I want to boot up via the client, I get the following error:

"Error processing request: signal only works in main thread"

It then points to a bunch of files in various areas that I have not yet tracked down.

I have tried using a simple roslaunch call on each of the launch files I made individually for the nodes I want to launch (in this case turtlesim_node and turtle_teleop_key) and they boot up fine and work by just running roslaunch [package] turtlesim_launch.launch, etc.

Below is the code for my server:

#!/usr/bin/env python
#Filename: primary_server.py

import rospy
import roslaunch
from robot_man.srv import *

class StartUpServer(object):
    def __init__(self):
        self._nodes = []


    def handle_startup(self, names):
        self._temp = names.nodes.split(",") #This reades in the
        # information from the srv file sent by the client and
        # separates each node/package pair

        #This loop separates the input from pairs of 2 corresponding
        # to the package and node names the user inputs
        for i in range(len(self._temp)):
            self._nodes.append(self._temp[i].split())

        #This loop will launch each node that the user has specified
        for package, executable in self._nodes:
            print('package is: {0}, executable is: {1}'.format(package, executable))
            node = roslaunch.core.Node(package, executable)
            launch = roslaunch.scriptapi.ROSLaunch()
            launch.start()

            process = launch.launch(node)
            print('running node: %s'%executable)
        return StartUpResponse(self._nodes) #I will change this later


if __name__ == '__main__':
    rospy.init_node('startup_node')
    server = StartUpServer()
    rospy.Service('startup', StartUp, server.handle_startup)
    print('The servers are up and running')
    rospy.spin()

Here is the code for my client:

#!/usr/bin/env python
#Filename: primary_client_startup.py

import rospy
from robot_man.srv import *

def main(nodes):
    rospy.wait_for_service('startup')
    proxy = rospy.ServiceProxy('startup', StartUp)
    response = proxy(nodes)
    return response

if __name__ == '__main__':
    nodes = input('Please enter the node packages followed by \
    node names separated by spaces. \n To activate multiple nodes \
    separate entries with a comma > ')
    main(nodes)

Here is my srv file:

#This should be a string of space/comma separated values
string nodes
---
#This should return "success" if node/s start up successfully, else "fail"
string status

And finally, here are the two launch files I have made to launch the turtle simulator:

turtlesim_launch.launch

<launch>
    <node name="turtlesim_node" pkg="turtlesim" type="turtlesim_node" />
</launch>

turtle_teleop_launch.launch

<launch>
    <node name="turtle_teleop_key" pkg="turtlesim" type="turtle_teleop_key" />
</launch>

I have done a bit of google searching and found no similar problems for ROS (though there are some similar errors for Django and the like but they don't relate).

I appreciate the help!

P.S. It is worth noting that I make it to line 34 when the error occurs (process = launch.launch(node)).



Solution 1:[1]

actually that is mentioned in the documentation

You're not calling init_node() from the Python Main thread. Python only allows signals to be registered from the Main thread.

Look here rospyOverviewInitialization and Shutdown

Solution 2:[2]

A solution that works (but is quite dirty) is to remove the signal handler registration function:

    def dummy_function(): pass
    roslaunch.pmon._init_signal_handlers = dummy_function

This way you'll lose the ability to kill the node with CTRL+C, but at least you can start it.

Solution 3:[3]

I believe the problem is that you are trying to launch a node in a callback, which as user3732793 says isn't allowed. If you use append to Queue (or just a list) in the callback, then instead of just rospy.spin() check for items in the queue and then launch if they are there. I believe it will work. Here is an example

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user3732793
Solution 2 leosh
Solution 3 Batch