Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiprocessing Process terminate fails on Linux

I just noticed the problem with process terminate (from multiprocessing library) method on Linux. I have application working with multiprocessing library but... when I call terminate function on Windows everything works great, on the other hand Linux fails with this solution. As a replacement of process killing I was forced to use

os.system('kill -9 {}'.format(pid))

I know this isn't too smart, but it works. So I just wondering why this code works on Windows, but on Linux fails.

Example:

from multiprocessing import Process
import os

process=Process(target=foo,args=('bar',))
pid=process.pid
process.terminate() # works on Windows only

...

os.sytem('kill -9 {}'.format(pid)) # my replacements on Linux

My configuration: python 3.2.0 build 88445; Linux-2.6.32-Debian-6.0.4

This is a sample from my code. I hope it will be sufficient.

def start_test(timestamp,current_test_suite,user_ip):
    global_test_table[timestamp] = current_test_suite
    setattr(global_test_table[timestamp], "user_ip", user_ip)
    test_cases = global_test_table[timestamp].test_cases_table

    test_cases = test_cases*int(global_test_table[timestamp].count + 1)
    global_test_table[timestamp].test_cases_table = test_cases
    print(test_cases)
    print(global_test_table[timestamp].test_cases_table)

    case_num = len(test_cases)
    Report.basecounter = Report.casecounter = case_num

    setattr(global_test_table[timestamp], "case_num", case_num)
    setattr(global_test_table[timestamp], "user_current_test", 0)

    try:
        dbobj=MySQLdb.connect(*dbconnector)
        dbcursor=dbobj.cursor()

        dbcursor.execute(sqlquery_insert_progress.format(progress_timestamp = str(timestamp), user_current_test = global_test_table[timestamp].user_current_tes$
    except :...

    for i in range(case_num):
        user_row = global_test_table[timestamp]
        current_test_from_tests_table = user_row.test_cases_table[i]
        unittest.TextTestRunner(verbosity=2).run(suite(CommonGUI.get_address(CommonGUI,current_test_from_tests_table[1], current_test_from_tests_table[2], user$
        global_test_table[timestamp].user_current_test = i + 1
        try:
            dbobj=MySQLdb.connect(*dbconnector)
            dbcursor=dbobj.cursor()

            dbcursor.execute(sqlquery_update_progress.format(progress_timestamp = str(timestamp), user_current_test = global_test_table[timestamp].user_current$
        except :...

@cherrypy.expose()
def start_test_page(self, **test_suite):
    timestamp = str(time.time())
    user_ip = cherrypy.request.remote.ip
    if on_server():
        sys.stdout=sys.stderr=open("/var/log/cherrypy/test_gui/{file}.log".format(file=timestamp),"a")
    current_test_suite = self.parse_result(**test_suite)
    #global_test_table[timestamp] = current_test_suite
    #setattr(global_test_table[timestamp], "user_ip", user_ip)
    user_test_process = Process(target=start_test, args=(timestamp,current_test_suite,user_ip))
    users_process_table[timestamp] = user_test_process
    user_test_process.start()
    return '''{"testsuite_id" : "''' + str(timestamp) + '''"}'''

@cherrypy.expose()
def stop_test(self, timestamp):
    if timestamp in users_process_table:
        if on_server():
            user_process_pid = users_process_table[timestamp].pid
            os.system("kill -9 " + str(user_process_pid))
        else:
            users_process_table[timestamp].terminate()
        del users_process_table[timestamp]
    else:
        return "No process exists"
like image 373
falek.marcin Avatar asked May 10 '12 07:05

falek.marcin


People also ask

How do you terminate a process in multiprocessing?

A process can be killed by calling the Process. kill() function. The call will only terminate the target process, not child processes. The method is called on the multiprocessing.

How do I stop all processes in Python multiprocessing?

You can kill all child processes by first getting a list of all active child processes via the multiprocessing. active_children() function then calling either terminate() or kill() on each process instance.

What is multiprocessing pipe?

In multiprocessing, a pipe is a connection between two processes in Python. It is used to send data from one process which is received by another process. Under the covers, a pipe is implemented using a pair of connection objects, provided by the multiprocessing.


1 Answers

From the docs:

terminate()

Terminate the process. On Unix this is done using the SIGTERM signal; on Windows TerminateProcess() is used. Note that exit handlers and finally clauses, etc., will not be executed.

Note that descendant processes of the process will not be terminated – they will simply become orphaned.

So it looks like you have to make sure that your process handles the SIGTERM signal correctly.

Use signal.signal to set a signal handler.

To set a SIGTERM signal handler that simply exist the process, use:

import signal
import sys
signal.signal(signal.SIGTERM, lambda signum, stack_frame: sys.exit(1))

EDIT

A Python process normally terminates on SIGTERM, I don't know why your multiprocessing process doesn't terminate on SIGTERM.

like image 125
codeape Avatar answered Oct 11 '22 12:10

codeape