http://www.cs.colostate.edu/~cs370/Spring15/Workbook/thread_ex.txt
My professor provided the above sample code (Not duplicating to preserve his IP), and I'm confused by the output.
There are two functions being used as start routines, T1 and T2, and there are two separate for loops starting new threads. There is a tid assigned to each thread that should match the value of t when the thread was created, but there are several threads of the same function with the same tid as seen at the end of his sample output, i.e. there are two T1 threads with the tid 1. Why is this happening? If there are 4 T1 threads, shouldn't it generate tids 0-3?
Your professor designed these incorrectly, t changes its value in the main thread and is accessed by other threads without using mutual exclusion.
Here's what clang's TSan has to say:
==================
WARNING: ThreadSanitizer: data race (pid=5810)
Read of size 4 at 0x7fff193c03e4 by thread T1:
#0 T1(void*) /home/brian/src/so/threading/ex.cpp:16 (exe+0x0000000a0497)
Previous write of size 4 at 0x7fff193c03e4 by main thread:
#0 main /home/brian/src/so/threading/ex.cpp:61 (exe+0x0000000a0881)
Location is stack of main thread.
Thread T1 (tid=5812, running) created by main thread at:
#0 pthread_create ??:0 (exe+0x000000045a8b)
#1 main /home/brian/src/so/threading/ex.cpp:62 (exe+0x0000000a085a)
SUMMARY: ThreadSanitizer: data race /home/brian/src/so/threading/ex.cpp:16 T1(void*)
==================
... followed by ...
T1 [0] count = 12
==================
WARNING: ThreadSanitizer: data race (pid=5810)
Write of size 1 at 0x7ff2f8aa2c80 by main thread:
#0 main /home/brian/src/so/threading/ex.cpp:70 (exe+0x0000000a0964)
Previous read of size 1 at 0x7ff2f8aa2c80 by thread T1:
#0 T1(void*) /home/brian/src/so/threading/ex.cpp:18 (exe+0x0000000a04de)
As if synchronized via sleep:
#0 sleep ??:0 (exe+0x00000003f7bd)
#1 main /home/brian/src/so/threading/ex.cpp:69 (exe+0x0000000a0952)
Thread T1 (tid=5812, running) created by main thread at:
#0 pthread_create ??:0 (exe+0x000000045a8b)
#1 main /home/brian/src/so/threading/ex.cpp:62 (exe+0x0000000a085a)
SUMMARY: ThreadSanitizer: data race /home/brian/src/so/threading/ex.cpp:70 main
==================
T1 thread 1 done.
Related
In gdb, when you run next command. It apply to innermost frame instead of selected frame. How to ask to gdb to break in next line of the selected frame?
For exemple:
Set a breakpoint in a sub-function:
(gdb) b subfunc
Breakpoint 1 at 0x400f09: file prog.c, line 94.
(gdb) c
Continuing.
Breakpoint 1 at 0x400f09: file prog.c, line 94.
94 void subfunc() {
Change selected frame:
(gdb) up
#1 0x0000000000400f7e in main (argc=1, argv=0x7fffffffe468) at prog.c:70
70 subfunc();
I want to stop at line 71 of prog.c:
(gdb) n
95 i = 0;
... but it stop line 95 of prog.c.
I finally found what I want. advance allow to continue until a particular line. Thus advance +1 do the job. It can be abbreviated adv +1.
You can do this with a temporary breakpoint offset from the current line in the selected frame :
tbreak +1
continue
Abbreviated:
tb +1
c
Since the question is
gdb: apply “next” to selected frame instead of innermost frame
The accepted answer is "advance + 1" is not so correct, which only works if the next line of selected frame could be hit.
advance -- Continue the program up to the given location (same form as args for break command)
A general solution is:
Switch to the inferior frame of the selected frame, finish it and step the program.
frame x-1
fin
n
where x is the selected frame.
Ref:
finish -- Execute until selected stack frame returns
next -- Step program
frame -- Select and print a stack frame
I want to receive a string from an array using a variables' integer as the array index. But it is not working.
Attempt 1
; Suspended | 0 = No, 1 = Yes
global Suspended := 0
global SuspendedMsg := ["The script has been paused.","The script has been re-activated."]
Pause::
Suspend
if suspended = 0 ; If script is not suspended
{
TrayTip, Paused, SuspendedMsg[Suspended], 3
Suspended++
} else ; If it is suspended
{
TrayTip, Activated, SuspendedMsg[Suspended], 3
Suspended--
}
return
Attempt #1 will just display the string "SuspendedMsg[Suspended]" because I don't know where to set the variable indicator %. Even if I set it to SuspendedMsg[%Suspended%] it will either display [1] or [0].
Attempt 2
; Suspended | 0 = No, 1 = Yes
global Suspended := 0
global SuspendedMsg := ["The script has been paused.","The script has been re-activated."]
global SendSuspendMsg := SuspendedMsg[Suspended]
Pause::
Suspend
if suspended = 0 ; If script is not suspended
{
TrayTip, Paused, %SendSuspendMsg%, 3
Suspended++
} else ; If it is suspended
{
TrayTip, Activated, %SendSuspendMsg%, 3
Suspended--
}
return
Attempt #2 won't do as well, it doesn't even display any message. I tried fiddling arround with % inside the global SendSuspendMsg := SuspendedMsg[Suspended] variable but it won't do no good. Anyone care to help me out?
#Blauhim missed an important point, although his answer is mostly correct. First the Index in an Array when created like you did, always starts at 1, then proceeds to 2 etc, etc... So your code was flawed when you tried to use your Boolean variable to call to an index as a 0 Index does not exist (not to mention that you didn't force and Expression on that TrayTip Command).
; Set our variable to 1 why? Because we are going to use a Logical switch below.
Suspended := 1
; This was correct format and I left it, although I removed Global's as they are not needed
SuspendedMsg := ["The script has been paused.","The script has been re-activated."]
Pause::
; Suspend toggles each time it's called
Suspend
; Here we are toggling the value of our variable using !
; We started with a 1 so that it would be correctly
;Changed to a 0 for the code below.
suspended := !suspended
; Nothing changed here
if suspended = 0 ; If script is not suspended
{
; In order to pass an Array or Object or Expression to a Command you Force it
; using the a Percent Sign with a space on either side.
; Also note you were trying to use your Logical True/False 0 or 1 variable to
; itterate. This didn't work because Array's always start with an Index of 1.
; Below I've accounted for this by simply added a 1 to your suspended so it correctly
; points to the Index in our Array.
TrayTip, Paused, % SuspendedMsg[suspended + 1], 3
} else ; If it is suspended
{
TrayTip, Activated, % SuspendedMsg[suspended + 1], 3
}
return
Instead of TrayTip, Paused, SuspendedMsg[Suspended], 3 or TrayTip, Paused, SuspendedMsg[%Suspended%], 3, try
TrayTip, Paused, % SuspendedMsg[Suspended], 3
. TrayTip asks you for a
specify the message to display
which means as much as a String. So, variables names aren't handled as variables here, but as strings instead (as most of the times in commands). It would make sense to state TrayTip, Paused, %SuspendedMsg[%Suspended%]%, 3
, but you cannot nest variable's percent signs. So, we'll have to use the percent sign to force an expression:
Force an expression: An expression can be used in a parameter that does not directly support it (except OutputVar parameters) by preceding the expression with a percent sign and a space or tab. In [v1.1.21+], this prefix can be used in the InputVar parameters of all commands except the traditional IF commands (use If (expression) instead). This technique is often used to access arrays.
Concerning your second problem: I don't think Arrays can be declared like that, can they..? (but I'm not sure). Also see this short article. So I guess the problem lies within the 3rd line of your code, because the rest of it looks good to me
When using lldb to debug a program, the program crashes and I print "bt" to backtrace. But even I scroll all the way back to the top of the screen, I still don't see the where the program is crashed because the backtrace is too large.
If you're using Terminal.app on Mac OS X, you can increase the size of your scroll-back buffer by opening the Preferences window for Terminal, click on the Profiles tab, there will be a series of buttons on the right, "Text / Window / Shell / Keyboard / Advanced". Under "Window" under "Scrollback" you can select a number of rows, or whether Terminal should limit the scrollback buffer to a number of lines.
Also, in lldb, the bt command accepts an argument which is the number of stack frames to show. It sounds like it's the first few stack frames that you're having trouble seeing, so this is exactly what you want. For instance, here I have bt only showing me the first two stack frames:
(lldb) bt
* thread #1: tid = 0x09bd, 0x00007fff888194de libsystem_kernel.dylib`mach_msg_trap + 10, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
* #0: 0x00007fff888194de libsystem_kernel.dylib`mach_msg_trap + 10
#1: 0x00007fff8881864f libsystem_kernel.dylib`mach_msg + 55
#2: 0x00007fff85c75b34 CoreFoundation`__CFRunLoopServiceMachPort + 212
#3: 0x00007fff85c74ffb CoreFoundation`__CFRunLoopRun + 1371
#4: 0x00007fff85c74858 CoreFoundation`CFRunLoopRunSpecific + 296
#5: 0x000000010148f497 Dock`___lldb_unnamed_function2$$Dock + 1202
#6: 0x00007fff8e7fd5c9 libdyld.dylib`start + 1
#7: 0x00007fff8e7fd5c9 libdyld.dylib`start + 1
(lldb) bt 2
* thread #1: tid = 0x09bd, 0x00007fff888194de libsystem_kernel.dylib`mach_msg_trap + 10, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
* #0: 0x00007fff888194de libsystem_kernel.dylib`mach_msg_trap + 10
#1: 0x00007fff8881864f libsystem_kernel.dylib`mach_msg + 55
(lldb)
my python code goes like this:
def a():
...
...
subprocess.call()
...
...
def b():
...
...
and so on.
My task:
1) If subprocess.call() returns within 3 seconds, my execution should continue the moment subprocess.call() returns.
2) If subprocess.call() does not return within 3 seconds, the subprocess.call() should be terminated and my execution should continue after 3 seconds.
3) Until subprocess.call() returns or 3 seconds finishes, the further execution should not take place.
This can be done with threads but how?
Relevant part of the real code goes like this:
...
cmd = ["gcc", "-O2", srcname, "-o", execname];
p = subprocess.Popen(cmd,stderr=errfile)//compiling C program
...
...
inputfile=open(input,'w')
inputfile.write(scanf_elements)
inputfile.close()
inputfile=open(input,'r')
tempfile=open(temp,'w')
subprocess.call(["./"+execname,str(commandline_argument)],stdin=inputfile,stdout=tempfile); //executing C program
tempfile.close()
inputfile.close()
...
...
I am trying to compile and execute a C program using python.
When I am executing C program using subprocess.call() and suppose if the C program contains an infinite loop, then the subprocess.call() should be terminated after 3 seconds and the program should continue. I should be able to know whether the subprocess.call() was forcefully terminated or successfully executed so that I can accordingly print the message in the following code.
The back end gcc is of linux.
My task:
1) If subprocess.call() returns within 3 seconds, my
execution should continue the moment subprocess.call() returns.
2) If
subprocess.call() does not return within 3 seconds, the
subprocess.call() should be terminated and my execution should
continue after 3 seconds.
3) Until subprocess.call() returns or 3
seconds finishes, the further execution should not take place.
On *nix, you could use signal.alarm()-based solution:
import signal
import subprocess
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
# start process
process = subprocess.Popen(*your_subprocess_call_args)
# set signal handler
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(3) # produce SIGALRM in 3 seconds
try:
process.wait() # wait for the process to finish
signal.alarm(0) # cancel alarm
except Alarm: # subprocess does not return within 3 seconds
process.terminate() # terminate subprocess
process.wait()
Here's a portable threading.Timer()-based solution:
import subprocess
import threading
# start process
process = subprocess.Popen(*your_subprocess_call_args)
# terminate process in 3 seconds
def terminate():
if process.poll() is None:
try:
process.terminate()
except EnvironmentError:
pass # ignore
timer = threading.Timer(3, terminate)
timer.start()
process.wait()
timer.cancel()
Finally the below code worked:
import subprocess
import threading
import time
def process_tree_kill(process_pid):
subprocess.call(['taskkill', '/F', '/T', '/PID', process_pid])
def main():
cmd = ["gcc", "-O2", "a.c", "-o", "a"];
p = subprocess.Popen(cmd)
p.wait()
print "Compiled"
start = time.time()
process = subprocess.Popen("a",shell=True)
print(str(process.pid))
# terminate process in timeout seconds
timeout = 3 # seconds
timer = threading.Timer(timeout, process_tree_kill,[str(process.pid)])
timer.start()
process.wait()
timer.cancel()
elapsed = (time.time() - start)
print elapsed
if __name__=="__main__":
main()
If you're willing to convert your call to a Popen constructor instead of call (same way you are running gcc), then one way to approach this is to wait 3 seconds, poll the subprocess, and then take action based on whether its returncode attribute is still None or not. Consider the following highly contrived example:
import sys
import time
import logging
import subprocess
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)
if __name__ == '__main__':
logging.info('Main context started')
procCmd = 'sleep %d' % int(sys.argv[1])
proc = subprocess.Popen(procCmd.split())
time.sleep(3)
if proc.poll() is None:
logging.warning('Child process has not ended yet, terminating now')
proc.terminate()
else:
logging.info('Child process ended normally: return code = %s' % str(proc.returncode))
logging.info('Main context doing other things now')
time.sleep(5)
logging.info('Main context ended')
And this results in different logging output depending upon whether the child process completed within 3 seconds or not:
$ python parent.py 1
2015-01-18 07:00:56,639 INFO Main context started
2015-01-18 07:00:59,645 INFO Child process ended normally: return code = 0
2015-01-18 07:00:59,645 INFO Main context doing other things now
2015-01-18 07:01:04,651 INFO Main context ended
$ python parent.py 10
2015-01-18 07:01:05,951 INFO Main context started
2015-01-18 07:01:08,957 WARNING Child process has not ended yet, terminating now
2015-01-18 07:01:08,957 INFO Main context doing other things now
2015-01-18 07:01:13,962 INFO Main context ended
Note that this approach above will always wait 3 seconds even if the subprocess completes sooner than that. You could convert the above into something like a loop that continually polls the child process if you want different behavior - you'll just need to keep track of how much time has elapsed.
#!/usr/bin/python
import thread
import threading
import time
import subprocess
import os
ret=-1
def b(arg):
global ret
ret=subprocess.call(arg,shell=True);
thread.start_new_thread(b,("echo abcd",))
start = time.time()
while (not (ret == 0)) and ((time.time() - start)<=3):
pass
if (not (ret == 0)) :
print "failed"
elapsed = (time.time() - start)
print elapsed
thread.exit()
elif (ret == 0):#ran before 3 sec
print "successful"
elapsed = (time.time() - start)
print elapsed
I have written the above code which is working and satisfying all my contstraints.
The link https://docs.python.org/2/library/thread.html says:
thread.exit()
Raise the SystemExit exception. When not caught, this will cause the thread to exit silently.
So I suppose there should be no problem of orphan processes, blocked resources, etc. Please suggest.
I try to draw out the process according to the code but I really need some explanation in why, here is the question:
B() {
pid_t pid;
if ((pid = fork()) != 0)
waitpid(pid,NULL,0);
printf("2");
if(fork() ==0)
{ printf("3"); exit(0); }
printf("5");
exit(0);
}
Which one are illegals output?
232553, 235325, 232355, 235253, 252533...
This is the process I draw out according to the code and my understanding of fork.
___3 (exit so no more here)
|
__2__|___5 (I guess 5 should be here)
| |
| |
____|____(wait)|(start again since printf 3 process end)
So I'm stuck right there... Any help is appreciated.
Okay, there are two forks. Here is control flow, from left to right, with parents on top and children on the bottom:
+-- B ---- waitpid() --+ +-- "5" -- E
| | |
A --+ fork() +-- C -- "2" -- D -+ fork()
| | |
+----------------------+ +-- "3" -- F
So, what do we know?
"2", "5", and "3" each appear twice (90 possibilities)
No prefix may contain more "3" than "2" (30 possibilities)
No prefix may contain more "5" than "2" (16 possibilities)
The second "2" must be preceded by the first "5" (7 possibilities)
The 7 possibilities are:
2,3,5,2,3,5
2,3,5,2,5,3
2,5,2,3,3,5
2,5,2,3,5,3
2,5,2,5,3,3
2,5,3,2,3,5
2,5,3,2,5,3
This should be the program path (x denotes termination):
---+--(wait)-2-+-5-x
| |
+-2-+-5-x +-3-x
|
+-*3-x
After the first fork, the parent waits for the child to finish. But in case of second fork, it does not wait. So, * marked 3 can be printed anywhere after first 2. The order of printing 5 and 3 after second fork also can not be determined. Therefore, the possible outputs are:
25235*3
25253*3
2523*35
2525*33
252*335
252*353
25*3235
25*3253
2*35235
2*35253
Since the order of execution with fork() is not deterministic, you can only expect that each integer (i.e., 2, 3 and 5) will be printed twice. The order depends on how the scheduler chooses to schedule the processes.
You can force a particular order using sleep commands or some other synchronization primitive.
The first fork() splits the process into 2 parts (parent and child). The parent waits and the child prints 2.
Then the child does fork(); and then child prints 5 and exits (which allows the parent to start running again) while the child's child (grandchild?) prints 3. This can happen in any order.
The parent continues and prints 2 (this may happen before or after the grandchild prints 3; but after the now terminated child printed 5).
Then the parent does fork(); and the parent prints 5 and it's second child prints 2 (which can happen in any order, and may happen before the grandchild prints 5).
The first fork creates a child and waits for it. So the main program only goes on running as soon as the first child exits.
So the first output is "the child's" 2.
Then a 3 and a 5 is printed, in any order. Only after the 3 or the 5 the second 2 can occur, and then the second 3 and/or 5.
So
232553 is ok
235325 is not ok, as the 2nd 3 comes before the 2nd 2
232355 is ok
235253 is ok
252533 is ok