Unexpected closure of Python program while using ReadProcessMemory from kernel32 - python

I have a really weird behavior from my python program and I need your help to understand where to search.
I made quite a big a program using rpm (ReadProcessMemory from kernel32 windows DLL).
My issue is that my program sometimes closes without any Traceback nor Error.
It does not go to the end and just stops running.
Let's show a simple piece of code :
rPM =ctypes.WinDLL('kernel32',use_last_error=True).ReadProcessMemory
rPM.argtypes = [wintypes.HANDLE,wintypes.LPCVOID,wintypes.LPVOID,ctypes.c_size_t,ctypes.POINTER(ctypes.c_size_t)]
rPM.restype = BOOL
def ReadMemory(self, pPath):
pPath = int.from_bytes(pPath,"little")
PathBuffer = ctypes.create_string_buffer(40)
bytes_read = ctypes.c_size_t()
if not rPM(self.handle,pPath,PathBuffer,40, bytes_read ):
Logger.error("Cannot read Path from memory")
return None
DynamicX=struct.unpack("H", PathBuffer[0x02:0x02 + 2])[0]
DynamicY=struct.unpack("H", PathBuffer[0x06:0x06 + 2])[0]
StaticX=struct.unpack("H", PathBuffer[0x10:0x10 + 2])[0]
StaticY=struct.unpack("H", PathBuffer[0x14:0x14 + 2])[0]
return DynamicX, DynamicY, StaticX, StaticY
for i in range(50):
Logger.debug("Read Info")
ReadMemory()
Logger.debug("Finished Read Info")
Logger.debug("End of program")
Sometimes it will stop at occurence #30, sometime # 45, etc...
and sometimes it comes without any error at all and goes to the end, when running a failing program again it goes through this loop and fail in another one.
The memory I'm reading is the same between two different executions.
How could I get the reason for the closure ? I tried try: except: but never entering into the except catcher.
I'm using python 3.9.1 in windows.
Do you have a hint please, I really don't understand why and cannot fix it :(
Thanks !
Edit :
After more invetigation the crash is not always on rpm function, sometimes it's when using struct.unpack and sometimes (even stranger !) it's during the return statment !
I found on windows error logs a lot of APPCRASH :
Signature du problème
Nom d’événement du problème : APPCRASH
Nom de l’application: python.exe
Version de l’application: 3.7.6150.1013
Horodatage de l’application: 5dfac7ba
Nom du module défaillant: python37.dll
Version du module défaillant: 3.7.6150.1013
Horodateur du module défaillant: 5dfac78b
Code de l’exception: c0000005
Décalage de l’exception: 000000000004d547
Version du système: 10.0.19042.2.0.0.768.101
Identificateur de paramètres régionaux: 1036
Information supplémentaire n° 1: c75e
Information supplémentaire n° 2: c75e78fc0ea847c06758a77801e05e29
Information supplémentaire n° 3: 2730
Information supplémentaire n° 4: 27303d8be681197ea114e04ad6924f93
But I still don't know why it's crashing, I checked the memory and CPU usage of my computer and does not go higher than 60%.
I tried (as you can see) also to change my python version to another one.

Thanks, finally found the issue !
First step was to add :
faulthandler.enable()
It enables the windows crash event to be catched and display in std.err or a file.
It has given me the same thing as #Mark Tolonen said. Read access violation !
After knowing that I double checked my ReadMemory and the buffer size was bigger than expected. It means sometimes I tried to read more than the process memory and tried to read "somewhere else" : Eureka !
Thanks for your tips Mark, I learnt a lot with this one !

Related

How to change username of job in print queue using python & win32print

I am trying to change the user of a print job in the queue, as I want to create it on a service account but send the job to another users follow-me printing queue. I'm using the win32 module in python. Here is an example of my code:
from win32 import win32print
JOB_INFO_LEVEL = 2
pclExample = open("sample.pcl")
printer_name = win32print.GetDefaultPrinter()
hPrinter = win32print.OpenPrinter(printer_name)
try:
jobID = win32print.StartDocPrinter(hPrinter, 1, ("PCL Data test", None, "RAW"))
# Here we try to change the user by extracting the job and then setting it again
jobInfoDict = win32print.GetJob(hPrinter, jobID , JOB_INFO_LEVEL )
jobInfoDict["pUserName"] = "exampleUser"
win32print.SetJob(hPrinter, jobID , JOB_INFO_LEVEL , jobInfoDict , win32print.JOB_CONTROL_RESUME )
try:
win32print.StartPagePrinter(hPrinter)
win32print.WritePrinter(hPrinter, pclExample)
win32print.EndPagePrinter(hPrinter)
finally:
win32print.EndDocPrinter(hPrinter)
finally:
win32print.ClosePrinter(hPrinter)
The problem is I get an error at the win32print.SetJob() line. If JOB_INFO_LEVEL is set to 1, then I get the following error:
(1804, 'SetJob', 'The specified datatype is invalid.')
This is a known bug to do with how the C++ works in the background (Issue here).
If JOB_INFO_LEVEL is set to 2, then I get the following error:
(1798, 'SetJob', 'The print processor is unknown.')
However, this is the processor that came from win32print.GetJob(). Without trying to change the user this prints fine, so I'm not sure what is wrong.
Any help would be hugely appreciated! :)
EDIT:
Using Python 3.8.5 and Pywin32 303
At the beginning I thought it was a misunderstanding (I was also a bit skeptical about the bug report), mainly because of the following paragraph (which apparently seems to be wrong) from [MS.Docs]: SetJob function (emphasis is mine):
The following members of a JOB_INFO_1, JOB_INFO_2, or JOB_INFO_4 structure are ignored on a call to SetJob: JobId, pPrinterName, pMachineName, pUserName, pDrivername, Size, Submitted, Time, and TotalPages.
But I did some tests and ran into the problem. The problem is as described in the bug: filling JOB_INFO_* string members (which are LPTSTRs) with char* data.
Submitted [GitHub]: mhammond/pywin32 - Fix: win32print.SetJob sending ANSI to UNICODE API (and none of the 2 errors pops up). It was merged to main on 220331.
When testing the fix, I was able to change various properties of an existing job, I was amazed that it didn't have to be valid data (like below), I'm a bit curious to see what would happen when the job would be executed (as now I don't have a connection to a printer):
Change pUserName to str(random.randint(0, 10000)) to make sure it changes on each script run (PrintScreens taken separately and assembled in Paint):
Ways to go further:
Wait for a new PyWin32 version (containing this fix) to be released. This is the recommended approach, but it will also take more time (and it's unclear when it will happen)
Get the sources, either:
from main
from b303 (last stable branch), and apply the (above) patch(1)
build the module (.pyd) and copy it in the PyWin32's site-packages directory on your Python installation(s). Faster, but it requires some deeper knowledge, and maintenance might become a nightmare
Footnotes
#1: Check [SO]: Run / Debug a Django application's UnitTests from the mouse right click context menu in PyCharm Community Edition? (#CristiFati's answer) (Patching UTRunner section) for how to apply patches (on Win).

What am I doing wrong to generate proper logon message?

I'm pretty new in quickfix, I've tried to read a lot and learn as much as I've could. But I'm facing a weird problem which I've could fix but I cannot understand why it's not working as expected.
First, my venue requires username and password, so I add both to 35=A message. This is expected, what it's not expected it's having field 141 automatically set in logon message, even when in cfg file this is not included, or at least not on purpose. And similar to SenderSubID, TargetCompID and TargetSubID which are required to my venue and having included them in config file are not considered in automatically generated Logon. What I'm doing in a wrong way? Maybe I'm using an incorrect AppDataDictionary, maybe I should change it to customize? Not sure how to fix this in a more smart way instead of using toAdmin to customize a lot of message fields which should be properly generated before.
Code snippet to fix the problem I'm facing
def toAdmin(self, message, sessionID):
# Hook que corre antes de enviar un mensaje al servidor fix
msg_type = fix.MsgType()
message.getHeader().getField(msg_type)
if msg_type.getString() is fix.MsgType_Logon:
message.removeField(141)
message.getHeader().setField(fix.StringField(34, "1"))
message.getHeader().setField(fix.SenderSubID("351"))
message.getHeader().setField(fix.StringField(1408, "T5.0"))
message.getHeader().setField(fix.TargetCompID("XXX"))
message.getHeader().setField(fix.TargetSubID("M3"))
message.setField(fix.Username("xxxxxxx"))
message.setField(fix.Password("xxxxxxx"))
This is my configuration file
[SESSION]
StartTime=00:00:00
SenderCompID=A899
SenderSubID=351
EndTime=00:00:00
ConnectionType=initiator
ApplVerID=9
BeginString=FIXT.1.1
DefaultApplVerID=9
TransportDataDictionary=FIXT11.xml
AppDataDictionary=FIXT11.xml
TargetCompID=XXX
TargetSubID=M3
SocketConnectPort=xxxx
SocketConnectHost=xx.xx.xx.xx
SocketUseSSL=Y
SSLEnable=Y
HeartBtInt=20
ReconnectInterval=30
ResetOnLogout=Y
ResetOnDisconnect=Y
SSLValidateCertificates=Y
ResetSeqNumFlag=N
Thanks a lot for your help, any idea would be welcome.
Regards
I think appart of removing ResetOn... not much more can be done. I've researched for same request in other languages (c#, Java and c) and proposal solution is always which I did. So I assume this is the best approach :(
Thanks a lot for your time and help.

Debugging with Numba

My first question here, tell me if I am doing things wrong.
My problem
I am writing a module using Numba. Of course I have run accross a segfault, and I can't find where it comes from. So I am trying to debug it using gdb from Numba, but it does not work: the segfault is raised but I get no information from where it comes from:
[Reading symbols]
28 ../sysdeps/unix/sysv/linux/nanosleep.c: Aucun fichier ou dossier de ce type.
0x00007feacc67ea30 in __GI___nanosleep (requested_time=0x7ffdfe227510,
remaining=0x7ffdfe227510) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
Breakpoint 1 at 0x7fea9d234150: file numba/_helperlib.c, line 1131.
Continuing.
double free or corruption (!prev)
51 ../sysdeps/unix/sysv/linux/raise.c: Aucun fichier ou dossier de ce type.
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
(gdb)
During the gdb initialisation, this is also printed in stderr:
attach: No such file or directory.
Note that I have already managed the ptrace problem mentioned here by setting kernel.yama.ptrace_scope=0
Reproducing Numba's debug example
I don't know if it counts as a working reproducer, but I tried to run the example from the Numba documentation that I mentionned earlier :
from numba import njit, gdb_init
import numpy as np
#njit(debug=True)
def foo(a, index):
gdb_init() # instruct Numba to attach gdb at this location, but not to pause execution
b = a + 1
c = a * 2.34
d = c[index] # access an address that is a) invalid b) out of the page
print(a, b, c, d)
bad_index = int(1e9) # this index is invalid
z = np.arange(10)
r = foo(z, bad_index)
print(r)
And I can't get the same output as they do:
[Reading symbols]
0x00007efcb5a60a30 in __GI___nanosleep (requested_time=0x7ffff4990f70,
remaining=0x7ffff4990f70) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28 ../sysdeps/unix/sysv/linux/nanosleep.c: Aucun fichier ou dossier de ce type.
Breakpoint 1 at 0x7efcabf3d150: file numba/_helperlib.c, line 1131.
Continuing.
Traceback (most recent call last):
File "/home/.../test_segfault.py", line 16, in <module>
r = foo(z, bad_index)
IndexError: index is out of bounds
[Inferior 1 (process 4299) exited with code 01]
My error message does not indicate me the exact line of the segfault, just the jitted function..
And again, I have this message, which may be the source of my problem..
attach: No such file or directory.
Could anyone help me make this work ?
Or a link to an equivalent question ? I have found the documentation and forums really short when it comes to debugging Numba.
Or maybe alternative ways to trace a segfault in Numba jitted functions ?
Thank you for reading me, I hope it is understandable.
the segfault is raised but I get no information from where it comes from
This is not segfault, this is SIGABRT because of double free or corruption that was detected by glibc. This kind of error is better debugged by Valgrind or AddressSanitizer, not gdb. If your program is relatively small use Valgrind because it is easier to use. If not I'd suggest to use AddressSanitizer.

Runtime Error (NZEC) - Python / Codechef

I'm getting started with Codechef. I submitted following code in python to solve this question.
The code below works fine with codechef's online (python) IDE as well as my local IDE. But, when I submit it on codechef, it results in Runtime Error (NZEC). Can someone explain to me the reason behind this?
withdrawCash = int(input())
totalCash = int(input())
if withdrawCash < totalCash and withdrawCash % 5 is 0:
totalCash = (totalCash - withdrawCash) - 0.5
print(totalCash)
The problem supplies both the inputs in a single line. Your code waits for input in 2 lines. Change it to:
withdrawCash,totalCash = map(int,raw_input.split())
NZEC (Non Zero Exit Code) occurs when your code doesn't return zero on exit. It can happen due to a number of reasons, but if splitting the input doesn't solve the problem, add an exception for EOFerror. Just write:
try:
withdrawCash = int(input().split()) # raw_input in the case of Python 2
except EOFerror:
print ("exit") # this is jst a pseudo statement `
Use indentation properly. I am currently using an android app of stack exchange in which writing code is not so easy. codechef is pretty poor when it comes to Python. Switch to any other lang for CP.
Try directly submitting the code without running it on Codechef ide because it with me also it showed the same but when I submitted directly I got submitted successfully. so Directly submit your code.

Adding testcase results to Quality Center Run from a outside Python Script

I want to try to add all the step details - Expected, Actual, Status,
etc. to a QC Run for a testcase of a TestSet from a Python Script
living outside the Quality Center.
I have come till here (code given below) and I don't know how to add
Step Expected and Step Actual Result. If anyone knows how do it,
please help me out!! Please, I don't want any QTP solutions.
Thanks,
Code-
# Script name - add_tsrun.py
# C:\Python27\python.exe
# This script lives locally on a Windows machine that has - Python 2.7, Win32 installed, IE8
# Dependencies on Windows Machine - Python 2.7, PythonWin32 installed, IE8, a QC Account, connectivity to QCServer
import win32com.client, os
tdc = win32com.client.Dispatch("TDApiOle80.TDConnection")
tdc.InitConnection('http://QCSERVER:8080/qcbin')
tdc.Login('USERNAME', 'PASSWORD')
tdc.Connect('DOMAIN_NAME', 'PROJECT')
tsFolder = tdc.TestSetTreeManager.NodeByPath('Root\\test_me\\sub_folder')
tsList = tsFolder.FindTestSets('testset1')
ts_object = tsList.Item(1)
ts_dir = os.path.dirname('testset1')
ts_name = os.path.basename('testset1')
tsFolder = tdc.TestSetTreeManager.NodeByPath(ts_dir)
tsList = tsFolder.FindTestSets(ts_name)
ts_object = tsList.Item(1)
TSTestFact = ts_object.TSTestFactory
TestSetTestsList = TSTestFact.NewList("")
ts_instance = TestSetTestsList.Item(1)
newItem = ts_instance.RunFactory.AddItem(None) # newItem == Run Object
newItem.Status = 'No Run'
newItem.Name = 'Run 03'
newItem.Post()
newItem.CopyDesignSteps() # Copy Design Steps
newItem.Post()
steps = newItem.StepFactory.NewList("")
step1 = steps[0]
step1.Status = "Not Completed"
step1.post()
## How do I change the Actual Result??
## I can access the Actual, Expected Result by doing this, but not change it
step1.Field('ST_ACTUAL') = 'My actual result' # This works in VB, not python as its a Syntax error!!
Traceback ( File "<interactive input>", line 1
SyntaxError: can't assign to function call
Hope this helps you guys out there. If you know the answer to set the
Actual Result, please help me out and let me know. Thanks,
Amit
As Ethan Furman answered in your previous question:
In Python () represent calls to functions, while [] represent indexing and mapping.
So in other words, you probably want to do step1.Field['ST_ACTUAL'] = 'My actual result'
Found the answer after a lot of Google Search :)
Simple -> Just do this:
step1.SetField("ST_ACTUAL", "my actual result") # Wohhooooo!!!!
If the above code fails to work, try to do the following:-
(OPTIONAL) Set your win32 com as follows- (Making ''Late Binding'')
# http://oreilly.com/catalog/pythonwin32/chapter/ch12.html
a. Start PythonWin, and from the Tools menu, select the item COM Makepy utility.
b. Using Windows Explorer, locate the client subdirectory (OTA COM Type Library)
under the main win32com directory and double-click the file makepy.py.
Thank you all...

Categories

Resources