how to decode .dSYM file to explicit DWARF format? - ios

DWARF is a debugging information format. The .dSYM file generated by Xcode contain the DWARF debugging information.
The Question is : how to decode the .dSYM file to get the human-readable DWARF information, which should like below.

On Mac OS X, you use the dwarfdump utility to dump the DWARF in .o files or in .dSYM bundles.
% dwarfdump fig7.o
----------------------------------------------------------------------
File: fig7.o (x86_64)
----------------------------------------------------------------------
.debug_info contents:
0x00000000: Compile Unit: length = 0x00000077 version = 0x0002 abbr_offset = 0x00000000 addr_size = 0x08 (next CU at 0x0000007b)
0x0000000b: TAG_compile_unit [1] *
AT_producer( "Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)" )
AT_language( DW_LANG_C99 )
AT_name( "fig7.c" )
AT_low_pc( 0x0000000000000000 )
AT_stmt_list( 0x00000000 )
AT_comp_dir( "/tmp" )
0x00000026: TAG_base_type [2]
AT_name( "int" )
AT_encoding( DW_ATE_signed )
AT_byte_size( 0x04 )
0x0000002d: TAG_variable [3]
AT_name( "a" )
AT_type( {0x00000026} ( int ) )
AT_external( 0x01 )
AT_decl_file( "/private/tmp/fig7.c" )
AT_decl_line( 1 )
AT_location( [0x0000000000000000] )
0x00000043: TAG_subprogram [4] *
AT_name( "foo" )
AT_decl_file( "/private/tmp/fig7.c" )
AT_decl_line( 2 )
AT_external( 0x01 )
AT_low_pc( 0x0000000000000000 )
AT_high_pc( 0x0000000000000006 )
AT_frame_base( rbp )
0x0000005d: TAG_variable [5]
AT_name( "b" )
AT_decl_file( "/private/tmp/fig7.c" )
AT_decl_line( 4 )
AT_type( {0x00000026} ( int ) )
AT_location( fbreg -4 )
0x0000006b: TAG_variable [5]
AT_name( "c" )
AT_decl_file( "/private/tmp/fig7.c" )
AT_decl_line( 5 )
AT_type( {0x00000026} ( int ) )
AT_location( fbreg -8 )
0x00000079: NULL
0x0000007a: NULL

Related

ESP8266-12F WiFi soft AP config.authmode failed

For a project I try do use the ESP8266 RTOS SDK.
First step I install the tools and the toolchain. The hello_world example and the other gpio example works fine. I try the softAP example and get a Guru Meditation Error: Core 0 panic'ed (StoreProhibited). Exception was unhandled Error. I figured out that the line 62 : .automode = WIFI_AUTH_WPA_WPA2_PSK not works. I tried WIFI_AUTH_WEP,WIFI_AUTH_WPA_PSK,WIFI_AUTH_WPA2_PSK but only with WIFI_AUTH_OPEN the softAP works. Anyone same behavior or some tips?
Console Trace:
ets Jan 8 2013,rst cause:1, boot mode:(3,6)
load 0x40100000, len 7040, room 16
tail 0
chksum 0xe5
load 0x3ffe8408, len 24, room 8
tail 0
chksum 0x6c
load 0x3ffe8420, len 3312, room 8
tail 8
chksum 0x75
csum 0x75
I (123) boot: ESP-IDF v3.4-rc 2nd stage bootloader
I (123) boot: compile time 19:41:32
I (207) qio_mode: Enabling default flash chip QIO
I (207) boot: SPI Speed : 40MHz
I (208) boot: SPI Mode : QOUT
I (212) boot: SPI Flash Size : 2MB
I (219) boot: Partition Table:
I (224) boot: ## Label Usage Type ST Offset Length
I (236) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (247) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (259) boot: 2 factory factory app 00 00 00010000 000f0000
I (271) boot: End of partition table
I (277) esp_image: segment 0: paddr=0x00010010 vaddr=0x40210010 size=0x52c80 (339072) map
I (406) esp_image: segment 1: paddr=0x00062c98 vaddr=0x40262c90 size=0x0f594 ( 62868) map
I (428) esp_image: segment 2: paddr=0x00072234 vaddr=0x3ffe8000 size=0x005fc ( 1532) load
I (429) esp_image: segment 3: paddr=0x00072838 vaddr=0x40100000 size=0x00080 ( 128) load
I (439) esp_image: segment 4: paddr=0x000728c0 vaddr=0x40100080 size=0x05560 ( 21856) load
I (460) boot: Loaded app from partition at offset 0x10000
I (481) wifi softAP: ESP_WIFI_MODE_AP
I (484) system_api: Base MAC address is not set, read default base MAC address from EFUSE
I (486) system_api: Base MAC address is not set, read default base MAC address from EFUSE
phy_version: 1163.0, 665d56c, Jun 24 2020, 10:00:08, RTOS new
I (557) phy_init: phy ver: 1163_0
I (567) wifi softAP: ----------------###------------
ESP_ERROR_CHECK failed: esp_err_t 0x2 (ERROR) at 0x4021f7cc
file: "softap_example_main.c" line 73
func: wifi_init_softap
expression: esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config)
abort() was called at PC 0x4021f7cf on core 0
Guru Meditation Error: Core 0 panic'ed (StoreProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x40221c72 PS : 0x00000030 A0 : 0x40221c70 A1 : 0x3ffeb550
A2 : 0x00000000 A3 : 0xffffffdb A4 : 0x00000001 A5 : 0x00000001
A6 : 0x00000000 A7 : 0x4026663c A8 : 0x00000020 A9 : 0x00000000
A10 : 0x00000008 A11 : 0x00000000 A12 : 0x00000000 A13 : 0x00000000
A14 : 0x00000000 A15 : 0x00000000 SAR : 0x0000001e EXCCAUSE: 0x0000001d
Backtrace: 0x40221c72:0x3ffeb550 0x4021f7d2:0x3ffeb560 0x4022182e:0x3ffeb570 0x40221894:0x3ffeb630 0x402118ef:0x3ffeb640
Example Code from GitHub: (examples/wifi/getting_started/softAP/main/softap_example_main.c)
/* WiFi softAP Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
/* The examples use WiFi configuration that you can set via project configuration menu.
If you'd rather not, just change the below entries to strings with
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN
static const char *TAG = "wifi softAP";
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
}
void wifi_init_softap()
{
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s",
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
}
void app_main()
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
wifi_init_softap();
}
You have to run idf.py menuconfig and set the SSID and password values.
Password´s under 8 characters gets a Guru-Meditation ERR if the
wifi_config.ap.authmode = WIFI_AUTH_WEP or,
wifi_config.ap.authmode = WIFI_AUTH_WPA_PSK or,
wifi_config.ap.authmode = WIFI_AUTH_WPA2_PSK . Other authmodes not yet testet.
To provid this Error, make sure your pw has more then 7 characters or/and set
the If-Condition after the wifi_config to:
if (strlen(EXAMPLE_ESP_WIFI_PASS) < 8) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
ESP_LOGI(TAG," pw-lenght under 8 charcters. Set WIFI_AUTH_OPEN");
}
Your WiFi is not protectet but your µC not crashes.

Ruby: any difference between == elsif != VS. == else?

Is there any practical difference in the results of these two little chunks of logic, if you are just checking for one specific condition and everything else is NOT X?
def country
if params[:ip_country_code] == "X"
{:api_key => 1}
else
{:api_key => 2}
end
end
vs.
def country
if params[:ip_country_code] == "X"
{:api_key => 1}
elsif params[:ip_country_code] != "X"
{:api_key => 2}
else
end
end
The difference if that using elsif generates one more comparison, therefore requiring a bit more work from the processor. You can disassemble it using following script:
code = <<~CODE
a = 4
if a == 4
puts "equal"
else
puts "not equal"
end
CODE
code2 = <<~CODE
a = 4
if a == 4
puts "equal"
elseif a != 4
puts "not equal"
end
CODE
puts RubyVM::InstructionSequence.compile(code).disasm
puts "\n\n----------------------\n\n"
puts RubyVM::InstructionSequence.compile(code2).disasm
Result for first one (if-else):
== disasm: #<ISeq:<compiled>#<compiled>>================================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1#-1, kwrest: -1])
[ 2] a
0000 trace 1 ( 1)
0002 putobject 4
0004 setlocal_OP__WC__0 2
0006 trace 1 ( 2)
0008 getlocal_OP__WC__0 2
0010 putobject 4
0012 opt_eq <callinfo!mid:==, argc:1, ARGS_SIMPLE>, <callcache>
0015 branchunless 26
0017 trace 1 ( 3)
0019 putself
0020 putstring "equal"
0022 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0025 leave ( 2)
0026 trace 1 ( 5)
0028 putself
0029 putstring "not equal"
0031 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0034 leave
While for the second (if-elsif):
== disasm: #<ISeq:<compiled>#<compiled>>================================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1#-1, kwrest: -1])
[ 2] a
0000 trace 1 ( 1)
0002 putobject 4
0004 setlocal_OP__WC__0 2
0006 trace 1 ( 2)
0008 getlocal_OP__WC__0 2
0010 putobject 4
0012 opt_eq <callinfo!mid:==, argc:1, ARGS_SIMPLE>, <callcache>
0015 branchunless 51
0017 trace 1 ( 3)
0019 putself
0020 putstring "equal"
0022 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0025 pop
0026 trace 1 ( 4)
0028 putself
0029 getlocal_OP__WC__0 2
0031 putobject 4
0033 opt_neq <callinfo!mid:!=, argc:1, ARGS_SIMPLE>, <callcache>, <callinfo!mid:==, argc:1, ARGS_SIMPLE>, <callcache>
0038 opt_send_without_block <callinfo!mid:elseif, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0041 pop
0042 trace 1 ( 5)
0044 putself
0045 putstring "not equal"
0047 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0050 leave ( 2)
0051 putnil ( 5)
0052 leave
As you see, second one generates more instructions so if done billions time, it will be slightly slower. I don't know if that's the "practicality" you meant.
In your case there will be even more overhead with accessing values from the hash. If you perform some really "heavy" operations in condition, it will be repeated twice and can have real impact on performance.
Case case
As asked in the comments, here's a version for case-based solution:
code3 = <<~CODE
a = 4
case a
when 4 then puts "equal"
else puts "not equal"
end
CODE
Result:
== disasm: #<ISeq:<compiled>#<compiled>>================================
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1#-1, kwrest: -1])
[ 2] a
0000 trace 1 ( 1)
0002 putobject 4
0004 setlocal_OP__WC__0 2
0006 trace 1 ( 2)
0008 getlocal_OP__WC__0 2
0010 dup
0011 opt_case_dispatch <cdhash>, 21
0014 dup ( 3)
0015 putobject 4
0017 checkmatch 2
0019 branchif 31
0021 pop ( 4)
0022 trace 1
0024 putself
0025 putstring "not equal"
0027 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0030 leave
0031 pop ( 5)
0032 trace 1 ( 3)
0034 putself
0035 putstring "equal"
0037 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0040 leave
Conclusion: this is only a bit longer that normal if-else and still much better that if-ifelse.
EDIT: I also noticed mistake in disassembled if-else, updated the answer.
if is good or two mutually exclusive choices.
elsif is usually used for multiple (or two not mutually exclusive) choices for different conditions.
multiple choices for the same condition are usually covered with with clause.
While there is no logical difference between those, the proper way to write this would be:
def country
value =
case params[:ip_country_code]
when "X" then 1
else 2
end
# or:
value =
if params[:ip_country_code] == 'X'
1
else
2
end
# or even with ternary:
value = params[:ip_country_code] == 'X' ? 1 : 2
{api_key: value}
end

decodingTCAP message - dialoguePortion

I'm writing an simulator (for learning purposes) for complete M3UA-SCCP-TCAP-MAP stack (over SCTP). So far M3UA+SCCP stacks are OK.
M3UA Based on the RFC 4666 Sept 2006
SCCP Based on the ITU-T Q.711-Q716
TCAP Based on the ITU-T Q.771-Q775
But upon decoding TCAP part I got lost on dialoguePortion.
TCAP is asn.1 encoded, so everything is tag+len+data.
Wireshark decode it differently than my decoder.
Message is:
62434804102f00676b1e281c060700118605010101a011600f80020780a1090607040000010005036c1ba1190201010201163011800590896734f283010086059062859107
Basically, my message is BER-decoded as
Note: Format: hex(tag) + (BER splitted to CLS+PC+TAG in decimal) + hex(data)
62 ( 64 32 2 )
48 ( 64 0 8 ) 102f0067
6b ( 64 32 11 )
28 ( 0 32 8 )
06 ( 0 0 6 ) 00118605010101 OID=0.0.17.773.1.1.1
a0 ( 128 32 0 )
60 ( 64 32 0 )
80 ( 128 0 0 ) 0780
a1 ( 128 32 1 )
06 ( 0 0 6 ) 04000001000503 OID=0.4.0.0.1.0.5.3
6c ( 64 32 12 )
...
So I can see begin[2] message containing otid[8], dialogPortion[11] and componentPortion[12].
otid and ComponentPortion are decoded correctly. But not dialogPortion.
ASN for dialogPortion does not mention any of these codes.
Even more confusing, wireshark decode it differently (oid-as-dialogue is NOT in the dialoguePortion, but as a field after otid, which is NOT as described in ITU-T documentation - or not as I'm understanding it)
Wireshark decoded Transaction Capabilities Application Part
begin
Source Transaction ID
otid: 102f0067
oid: 0.0.17.773.1.1.1 (id-as-dialogue)
dialogueRequest
Padding: 7
protocol-version: 80 (version1)
1... .... = version1: True
application-context-name: 0.4.0.0.1.0.5.3 (locationInfoRetrievalContext-v3)
components: 1 item
...
I can't find any reference for Padding in dialoguePDU ASN.
Can someone point me in the right direction?
I would like to know how to properly decode this message
DialoguePDU format should be simple in this case:
dialogue-as-id OBJECT IDENTIFIER ::= {itu-t recommendation q 773 as(1) dialogue-as(1) version1(1)}
DialoguePDU ::= CHOICE {
dialogueRequest AARQ-apdu,
dialogueResponse AARE-apdu,
dialogueAbort ABRT-apdu
}
AARQ-apdu ::= [APPLICATION 0] IMPLICIT SEQUENCE {
protocol-version [0] IMPLICIT BIT STRING {version1(0)} DEFAULT {version1},
application-context-name [1] OBJECT IDENTIFIER,
user-information [30] IMPLICIT SEQUENCE OF EXTERNAL OPTIONAL
}
Wireshark is still wrong :-). But then... that is display. It displays values correctly - only in the wrong section. Probably some reason due to easier decoding.
What I was missing was definition of EXTERNAL[8]. DialoguePortion is declared as EXTERNAL...so now everything makes sense.
For your message, my very own decoder says:
begin [APPLICATION 2] (x67)
otid [APPLICATION 8] (x4) =102f0067h
dialoguePortion [APPLICATION 11] (x30)
EXTERNAL (x28)
direct-reference [OBJECT IDENTIFIER] (x7) =00118605010101h
encoding:single-ASN1-type [0] (x17)
dialogueRequest [APPLICATION 0] (x15)
protocol-version [0] (x2) = 80 {version1 (0) } spare bits= 7
application-context-name [1] (x9)
OBJECT IDENTIFIER (x7) =04000001000503h
components [APPLICATION 12] (x27)
invoke [1] (x25)
invokeID [INTEGER] (x1) =1d (01h)
operationCode [INTEGER] (x1) = (22) SendRoutingInfo
parameter [SEQUENCE] (x17)
msisdn [0] (x5) = 90896734f2h
Nature of Address: international number (1)
Numbering Plan Indicator: unknown (0)
signal= 9876432
interrogationType [3] (x1) = (0) basicCall
gmsc-Address [6] (x5) = 9062859107h
Nature of Address: international number (1)
Numbering Plan Indicator: unknown (0)
signal= 26581970
Now, wireshark's padding 7 and my spare bits=7 both refer to the the protocol-version field, defined in Q.773 as:
AARQ-apdu ::= [APPLICATION 0] IMPLICIT SEQUENCE {
protocol-version [0] IMPLICIT BIT STRING { version1 (0) }
DEFAULT { version1 },
application-context-name [1] OBJECT IDENTIFIER,
user-information [30] IMPLICIT SEQUENCE OF EXTERNAL
OPTIONAL }
the BIT STRING definition, assigns name to just the leading bit (version1)... the rest (7 bits) are not given a name and wireshark consider them as padding

pthread deadlock issue when using pthread_cond_t

I am having horrible time trying to figure out why my sync. code gets deadlocked when using pthread library. Using winapi primitives is instead of pthread works with no problems. Using c++11 threading also works fine (unless compiled with visual studio 2012 service pack 3, there it just crashes - Microsoft accepted it as a bug.) Using pthread however proves to be a problem - at least running in on linux machine, haven't had a chance to try different OS.
I've written a simple program which illustrates the issue. The code is just showing the deadlock - I am well aware the design is pretty poor and can be written much better.
typedef struct _pthread_event
{
pthread_mutex_t Mutex;
pthread_cond_t Condition;
unsigned char State;
} pthread_event;
void pthread_event_create( pthread_event * ev , unsigned char init_state )
{
pthread_mutex_init( &ev->Mutex , 0 );
pthread_cond_init( &ev->Condition , 0 );
ev->State = init_state;
}
void pthread_event_destroy( pthread_event * ev )
{
pthread_cond_destroy( &ev->Condition );
pthread_mutex_destroy( &ev->Mutex );
}
void pthread_event_set( pthread_event * ev , unsigned char state )
{
pthread_mutex_lock( &ev->Mutex );
ev->State = state;
pthread_mutex_unlock( &ev->Mutex );
pthread_cond_broadcast( &ev->Condition );
}
unsigned char pthread_event_get( pthread_event * ev )
{
unsigned char result;
pthread_mutex_lock( &ev->Mutex );
result = ev->State;
pthread_mutex_unlock( &ev->Mutex );
return result;
}
unsigned char pthread_event_wait( pthread_event * ev , unsigned char state , unsigned int timeout_ms )
{
struct timeval time_now;
struct timespec timeout_time;
unsigned char result;
gettimeofday( &time_now , NULL );
timeout_time.tv_sec = time_now.tv_sec + ( timeout_ms / 1000 );
timeout_time.tv_nsec = time_now.tv_usec * 1000 + ( ( timeout_ms % 1000 ) * 1000000 );
pthread_mutex_lock( &ev->Mutex );
while ( ev->State != state )
if ( ETIMEDOUT == pthread_cond_timedwait( &ev->Condition , &ev->Mutex , &timeout_time ) ) break;
result = ev->State;
pthread_mutex_unlock( &ev->Mutex );
return result;
}
static pthread_t thread_1;
static pthread_t thread_2;
static pthread_event data_ready;
static pthread_event data_needed;
void * thread_fx1( void * c )
{
for ( ; ; )
{
pthread_event_wait( &data_needed , 1 , 90 );
pthread_event_set( &data_needed , 0 );
usleep( 100000 );
pthread_event_set( &data_ready , 1 );
printf( "t1: tick\n" );
}
}
void * thread_fx2( void * c )
{
for ( ; ; )
{
pthread_event_wait( &data_ready , 1 , 50 );
pthread_event_set( &data_ready , 0 );
pthread_event_set( &data_needed , 1 );
usleep( 100000 );
printf( "t2: tick\n" );
}
}
int main( int argc , char * argv[] )
{
pthread_event_create( &data_ready , 0 );
pthread_event_create( &data_needed , 0 );
pthread_create( &thread_1 , NULL , thread_fx1 , 0 );
pthread_create( &thread_2 , NULL , thread_fx2 , 0 );
pthread_join( thread_1 , NULL );
pthread_join( thread_2 , NULL );
pthread_event_destroy( &data_ready );
pthread_event_destroy( &data_needed );
return 0;
}
Basically two threads signaling each other - start doing something, and doing their own thing even if not signaled after a short timeout.
Any idea what it going wrong there?
Thanks.
The problem is the timeout_time parameter to pthread_cond_timedwait(). The way you increment it is eventually and quite soon going to have an invalid value there with nanosecond part bigger than or equal to billion. In this case pthread_cond_timedwait() perhaps return with EINVAL, and probably actually before waiting for the condition.
The problem can be found very quickly with valgrind --tool=helgrind ./test_prog (quite soon it said it had already detected 10000000 errors and gave up counting):
bash$ gcc -Werror -Wall -g test.c -o test -lpthread && valgrind --tool=helgrind ./test
==3035== Helgrind, a thread error detector
==3035== Copyright (C) 2007-2012, and GNU GPL'd, by OpenWorks LLP et al.
==3035== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==3035== Command: ./test
==3035==
t1: tick
t2: tick
t2: tick
t1: tick
t2: tick
t1: tick
t1: tick
t2: tick
t1: tick
t2: tick
t1: tick
==3035== ---Thread-Announcement------------------------------------------
==3035==
==3035== Thread #2 was created
==3035== at 0x41843C8: clone (clone.S:110)
==3035==
==3035== ----------------------------------------------------------------
==3035==
==3035== Thread #2's call to pthread_cond_timedwait failed
==3035== with error code 22 (EINVAL: Invalid argument)
==3035== at 0x402DB03: pthread_cond_timedwait_WRK (hg_intercepts.c:784)
==3035== by 0x8048910: pthread_event_wait (test.c:65)
==3035== by 0x8048965: thread_fx1 (test.c:80)
==3035== by 0x402E437: mythread_wrapper (hg_intercepts.c:219)
==3035== by 0x407DD77: start_thread (pthread_create.c:311)
==3035== by 0x41843DD: clone (clone.S:131)
==3035==
t2: tick
==3035==
==3035== More than 10000000 total errors detected. I'm not reporting any more.
==3035== Final error counts will be inaccurate. Go fix your program!
==3035== Rerun with --error-limit=no to disable this cutoff. Note
==3035== that errors may occur in your program without prior warning from
==3035== Valgrind, because errors are no longer being displayed.
==3035==
^C==3035==
==3035== For counts of detected and suppressed errors, rerun with: -v
==3035== Use --history-level=approx or =none to gain increased speed, at
==3035== the cost of reduced accuracy of conflicting-access information
==3035== ERROR SUMMARY: 10000000 errors from 1 contexts (suppressed: 412 from 109)
Killed
There is also two other minor comments:
For improved correctness, in your pthread_event_set() you could have the condition variable broadcast be done before mutex unlock (the effect of wrong ordering basically could break the determinism of the scheduling; helgrind complains about this issue too);
you could safely drop the mutex locking in pthread_event_get() to return the value of ev->State - this should be atomic operation.

Criteria: "undefined offset"

i have this schema below, i have generated the classes using symfony
and created a pair of objects using the form class generated.
moto:
marca: { type: varchar(255), required: true }
matricula: { type: integer, required: true }
Now i have this criteria:
$c = new Criteria();
$c->addSelectColumn('MAX('.MotoPeer::MATRICULA.')');
$max_matricula = MotoPeer::doSelect($c);
var_dump($max_matricula);
return $max_matricula;
When i call the criteria code It works ok, but these three notices
below are showed.
Any idea?
sf 1.4/propel 1.4
( ! ) Notice: Undefined offset: 2 in
/opt/lampp/htdocs/prueba/lib/
model/om/BaseMotoPeer.php on line 379
Call Stack
Time Memory Function Location 1 0.0008 328076
{main}( ) ../frontend_dev.php:0
2 0.1974 4333236
sfContext->dispatch( )
../frontend_dev.php:13 3 0.1974
4333264
sfFrontWebController->dispatch( )
../ sfContext.class.php:170 4
0.1981 4350256 sfController->forward( ) ../
sfFrontWebController.class.php:48 5
0.2134 4641000 sfFilterChain->execute( )
../sfController.class.php: 238 6
0.2138 4641808 sfRenderingFilter->execute( )
../ sfFilterChain.class.php:53 7
0.2138 4641808 sfFilterChain->execute( ) ../
sfRenderingFilter.class.php:33 8
0.2143 4642588 sfExecutionFilter->execute( )
../ sfFilterChain.class.php:53 9
0.2144 4643308 sfExecutionFilter->handleAction( )
../ sfExecutionFilter.class.php:42 10
0.2144 4643308 sfExecutionFilter->executeAction( )
../ sfExecutionFilter.class.php:78 11
0.2144 4643336 sfActions->execute( ) ../sfExecutionFilter.class.php: 92 12
0.2147 4644160 motoActions->executePrueba( )
../sfActions.class.php: 60 13
0.2212 5026172 MotoPeer::prueba( ) ../actions.class.php:14 14 0.2254
5285592 BaseMotoPeer::doSelect( )
../MotoPeer.php:26 15 0.2493
5756176 BaseMotoPeer::populateObjects(
) ../BaseMotoPeer.php: 241 16
0.2493 5756568 BaseMotoPeer::getPrimaryKeyHashFromRow(
) ../ BaseMotoPeer.php:400
( ! ) Notice: Undefined offset: 1 in
/opt/lampp/htdocs/prueba/lib/
model/om/BaseMoto.php on line 184 Call
Stack
Time Memory Function Location 1 0.0008 328076
{main}( ) ../frontend_dev.php:0
2 0.1974 4333236
sfContext->dispatch( )
../frontend_dev.php:13 3 0.1974
4333264
sfFrontWebController->dispatch( )
../ sfContext.class.php:170 4
0.1981 4350256 sfController->forward( ) ../
sfFrontWebController.class.php:48 5
0.2134 4641000 sfFilterChain->execute( )
../sfController.class.php: 238 6
0.2138 4641808 sfRenderingFilter->execute( )
../ sfFilterChain.class.php:53 7
0.2138 4641808 sfFilterChain->execute( ) ../
sfRenderingFilter.class.php:33 8
0.2143 4642588 sfExecutionFilter->execute( )
../ sfFilterChain.class.php:53 9
0.2144 4643308 sfExecutionFilter->handleAction( )
../ sfExecutionFilter.class.php:42 10
0.2144 4643308 sfExecutionFilter->executeAction( )
../ sfExecutionFilter.class.php:78 11
0.2144 4643336 sfActions->execute( ) ../sfExecutionFilter.class.php: 92 12
0.2147 4644160 motoActions->executePrueba( )
../sfActions.class.php: 60 13
0.2212 5026172 MotoPeer::prueba( ) ../actions.class.php:14 14 0.2254
5285592 BaseMotoPeer::doSelect( )
../MotoPeer.php:26 15 0.2493
5756176 BaseMotoPeer::populateObjects(
) ../BaseMotoPeer.php: 241 16
0.2578 5953424 BaseMoto->hydrate( ) ../BaseMotoPeer.php:408
( ! ) Notice: Undefined offset: 2 in
/opt/lampp/htdocs/prueba/lib/
model/om/BaseMoto.php on line 185 Call
Stack
Time Memory Function Location 1 0.0008 328076
{main}( ) ../frontend_dev.php:0
2 0.1974 4333236
sfContext->dispatch( )
../frontend_dev.php:13 3 0.1974
4333264
sfFrontWebController->dispatch( )
../ sfContext.class.php:170 4
0.1981 4350256 sfController->forward( ) ../
sfFrontWebController.class.php:48 5
0.2134 4641000 sfFilterChain->execute( )
../sfController.class.php: 238 6
0.2138 4641808 sfRenderingFilter->execute( )
../ sfFilterChain.class.php:53 7
0.2138 4641808 sfFilterChain->execute( ) ../
sfRenderingFilter.class.php:33 8
0.2143 4642588 sfExecutionFilter->execute( )
../ sfFilterChain.class.php:53 9
0.2144 4643308 sfExecutionFilter->handleAction( )
../ sfExecutionFilter.class.php:42 10
0.2144 4643308 sfExecutionFilter->executeAction( )
../ sfExecutionFilter.class.php:78 11
0.2144 4643336 sfActions->execute( ) ../sfExecutionFilter.class.php: 92 12
0.2147 4644160 motoActions->executePrueba( )
../sfActions.class.php: 60 13
0.2212 5026172 MotoPeer::prueba( ) ../actions.class.php:14 14 0.2254
5285592 BaseMotoPeer::doSelect( )
../MotoPeer.php:26 15 0.2493
5756176 BaseMotoPeer::populateObjects(
) ../BaseMotoPeer.php: 241 16
0.2578 5953424 BaseMoto->hydrate( ) ../BaseMotoPeer.php:408
EDIT: the first notice appears because i didn't write "id: ~" before the fields of the model. Here it goes the lines that causes the second and the third notices:
/**
* Hydrates (populates) the object variables with values from the database resultset.
*
* An offset (0-based "start column") is specified so that objects can be hydrated
* with a subset of the columns in the resultset rows. This is needed, for example,
* for results of JOIN queries where the resultset row includes columns from two or
* more tables.
*
* #param array $row The row returned by PDOStatement->fetch(PDO::FETCH_NUM)
* #param int $startcol 0-based offset column which indicates which restultset column to start with.
* #param boolean $rehydrate Whether this object is being re-hydrated from the database.
* #return int next starting column
* #throws PropelException - Any caught Exception will be rewrapped as a PropelException.
*/
public function hydrate($row, $startcol = 0, $rehydrate = false)
{
try {
var_dump($row);
$this->id = ($row[$startcol + 0] !== null) ? (int) $row[$startcol + 0] : null;
$this->marca = ($row[$startcol + 1] !== null) ? (string) $row[$startcol + 1] : null;//184
$this->matricula = ($row[$startcol + 2] !== null) ? (int) $row[$startcol + 2] : null;//185
I think, the second and the third notices are showed because in the criteria I'm just getting one column (maatricula). But how to do it so?
Javier
If you use the "AddSelectColumn" method:
$c->addSelectColumn('MAX('.MotoPeer::MATRICULA.')');
you cannot hydrate the object - you are not selecting all the columns. Hence do not call:
MotoPeer::doSelect($c);
Instead do this:
$c->addSelectColumn('MAX('.MotoPeer::MATRICULA.')');
$stmt = MotoPeer::doSelectStmt($c);
$max_matricula = $stmt->fetchColumn(0);
Here you execute the SQL statement and fetch the single value that you're interested in into the variable $max_matricula.

Resources